使数据库可用于远程连接

让我们从以下事实开始:有时您需要创建具有数据库连接的应用程序。 这样做是为了避免因为缺乏人手和技能而过多地钻研后端开发而专注于前端。 我不会说我的解决方案是安全的,但它确实有效。

由于我不喜欢付费托管,所以我在工作中使用网络,有一个白色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;
};

现在您可以安全地将此程序扔给任何人,并且无需重写它即可在本地运行。

来源: habr.com

添加评论