使數據庫可用於遠程連接

讓我們從以下事實開始:有時您需要創建具有數據庫連接的應用程序。 這樣做是為了避免因為缺乏人手和技能而過多地鑽研後端開發而專注於前端。 我不會說我的解決方案是安全的,但它確實有效。

由於我不喜歡付費託管,所以我在工作中使用網絡,有一個白色IP。 這是它的結構:

使數據庫可用於遠程連接

我可以訪問多台計算機,更準確地說,192.168.1.2(又名 192.168.0.2)有 Linux,192.168.0.3 有 Windows。 一般來說,對於我的應用程序,我選擇了 mysql 並查看了 Linux 上的內容。 它已經安裝在那裡,但沒有人知道密碼,而那些知道密碼的人也忘記了(那些在我之前工作過的人)。 得知沒人需要後,我刪除了它並嘗試重新安裝。 沒有足夠的內存,並且由於要修復此錯誤,我必須將顯示器和帶鼠標的鍵盤連接到它,因此我決定退出這項業務。 而且,Windows 機器功能更強大,加上一切,我自己家裡的筆記本電腦上就有它。 原則上我不會描述安裝本身,有很多關於它的手冊和視頻。 在 Windows 機器上安裝了 mysql 後,我決定將表從筆記本電腦備份到工作站。

它是這樣完成的(就我而言):

mysqldump -uroot -p your_base > dump_file.sql

接下來,我們在新數據庫中創建一個數據庫,並在“新”機器上恢復備份。

mysql -h localhost -u root -p

create database your_base;
use your_base;

mysql -uroot -p your_base < dump_file.sql

show tables;


帶有備份的文件必須放在新機器上,如果不在帶有該實用程序的目錄中,則可以使用它的完整路徑。 (我剛剛將備份上傳到github並將其克隆到新機器上)。 我會添加表格本身是如何創建的,但我沒有保存屏幕截圖,我認為即使對於 2-3 年級的學生來說這也不難。

當我恢復所有表後,就可以遠程訪問數據庫了。 一般來說,這樣的命令不會導致成功(只給出了讀select的權限)

create user 'client'@'%' IDENTIFIED by 'client';
grant select on your_base . * to 'client'@'%';
flush privileges;

更準確地說,我只能使用以下命令連接到數據庫,

mysql -h localhost -u client -pclient

而這個不能

mysql -h 192.168.0.3 -u client -pclient

它不適合我,我也無法以 root 身份通過這個地址進行連接。

mysql 工作台程序提供了幫助,在設置中將 localhost 更改為% 並且它可以工作,儘管客戶端沒有幫助。 現在您可以從控制台或任何地址的代碼連接到數據庫。

使數據庫可用於遠程連接

你還需要建立一個家庭或企業網絡並關閉Windows防火牆,否則你甚至無法ping通這台機器(並不是說它會連接到數據庫)。

一半的工作已經完成,然後我需要能夠從家裡連接到數據庫。

從網絡圖中可以看到,需要從192.168.0.3到192.168.1.1(路由器)上網,我們反方向走吧。 讓我們設置一條從 192.168.1.1 到 192.168.1.2 的路由,如下所示:

使數據庫可用於遠程連接

一般來說,圖片不顯示——我會用手寫:

route add 192.168.0.0 mask 255.255.255.0 gateway 192.168.1.2

只能在一個子網內進行此操作,即不能立即轉發到地址 192.168.0.2 或 192.168.0.3

這是必要的,以便路由器知道 192.168.0.0/24 子網的位置(了解網絡基礎知識很有用)。

現在我們將端口轉發3306(默認mysql端口(如果您在安裝過程中沒有更改))添加到地址192.168.1.2

使數據庫可用於遠程連接

現在最困難的就是在Linux機器上做轉發(它有兩個網卡192.168.1.2(enp3s1接口)和192.168.0.2(enp3s0接口),這樣網卡就知道從192.168.1.2轉發什麼到192.168.0.2,然後到我們裝有MySql 的Windows 機器。

sudo iptables -A FORWARD -i enp3s1 -o enp3s0 -p tcp --syn --dport 3306 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i enp3s1 -o enp3s0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -i enp3s0 -o enp3s1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -A PREROUTING -i enp3s1 -p tcp --dport 3306 -j DNAT --to-destination 192.168.0.3
sudo iptables -t nat -A POSTROUTING -o enp3s0 -p tcp --dport 3306 -d 192.168.0.3 -j SNAT --to-source 192.168.1.2
и последняя строчка сохраняет введенные команды чтобы они при перезапуске оси не стерлись
sudo service iptables-persistent save

那些。 第一行表示我們接受第一個連接,第二行和第三行表示可以雙向發送數據包,第四行和第五行表示目的地和源地址的替換。 瞧,您可以通過 mysql 從家裡連接。 最後,我的 C++ 代碼執行此操作:

//DataBaseConnection.cpp
#include "DataBaseConnection.h"

DataBaseConnection::DataBaseConnection()
{
}
void DataBaseConnection::Connect()
{
	// Получаем дескриптор соединения
	conn = mysql_init(NULL);
	if (conn == NULL)
	{
		// Если дескриптор не получен – выводим сообщение об ошибке
		fprintf(stderr, "Error: can'tcreate MySQL-descriptorn");
		//exit(1); //Если используется оконное приложение
	}
	// Подключаемся к серверу
	if (!mysql_real_connect(conn, "192.168.0.3", "root", "password", "your_base", NULL, NULL, 0))
	{
		// Если нет возможности установить соединение с сервером 
		// базы данных выводим сообщение об ошибке
		fprintf(stderr, "Error: can't connect to database: %sn", mysql_error(conn));
	}
	else
	{
		// Если соединение успешно установлено выводим фразу - "Success!"
		fprintf(stdout, "Success!n");
	}
}
std::vector<std::string> DataBaseConnection::Query()
{
	vectordrum.clear();
	std::string query = "SELECT * FROM drum where id=0";
	const char * q = query.c_str();
	qstate = mysql_query(conn, q);
	if (!qstate)
	{
		res = mysql_store_result(conn);
		while (row = mysql_fetch_row(res))
		{
			//printf("ID: %s,Position: %s, Image: %sn", row[0], row[1], row[2]);
			vectordrum.push_back(row[2]);
		}
	}
	else
	{
		std::cout << "Query failed:" << mysql_error(conn) << std::endl;
	}
	return vectordrum;
}
void DataBaseConnection::Close()
{
	// Закрываем соединение с сервером базы данных
	mysql_close(conn);
}
DataBaseConnection::~DataBaseConnection()
{
	vectordrum.clear();
}
//DataBaseConnection.h
#pragma once
#include <iostream>
#include <mysql.h>
#include <vector>
#pragma comment(lib,"mysqlcppconn.lib")
#pragma comment(lib,"libmysql.lib")
class DataBaseConnection
{
public:
	DataBaseConnection();
	void Connect();
	std::vector<std::string> Query();
	void Close();
	~DataBaseConnection();
	MYSQL *conn;
	MYSQL_ROW row;
	MYSQL_RES *res;
	int qstate;
	std::vector<std::string> vectordrum;
};

現在您可以安全地將此程序扔給任何人,並且無需重寫它即可在本地運行。

來源: www.habr.com

添加評論