一、在ubuntu系统中C/C++连接mysql
1. 更新并升级软件源
apt-get update apt-get upgrade
2. 安装c/c++解释器
apt-get install g++
安装后,执行 g++ --version 可显示版本信息
3. 安装mysql服务器(若不使用本地数据库,而使用远程数据库,或docker环境下使用宿主机mysql ,可跳过此步)
apt-get install mysql-client mysql-server
安装mysql时,中途会提示你设置用户密码等,请牢记!并在第6步的c++程序中,修改相应的数据库配置变量!顺便新建一个数据库供后面测试:
create database mydatabase; # 新建数据库
4. 安装C/C++连接mysql驱动包
apt-get install libmysqlclient-dev
5. 编写C++程序进行测试
vim test.cpp #include<stdio.h> #include<mysql/mysql.h> const char *db_host="localhost"; const char *db_user="root"; const char *db_pass="rootroot"; const char *db_name="mydatabase"; const int db_port=3306; int main () { MYSQL *mysql=mysql_init(NULL); //初始化数据库连接变量 if(mysql==NULL) { printf("Error:%s\n",mysql_error(mysql)); exit(1); } mysql = mysql_real_connect(mysql,db_host,db_user,db_pass,db_name, db_port,NULL,0); //连接mysql if(mysql) printf("Success!\n"); //连接成功 else printf("Failed!\n"); return 0; }
6. 编译C++程序并执行
g++ test.cpp -o test -lmysqlclient
注:末尾务必加上 -lmysqlclient 否则编译时找不到mysql库
./test
这是执行程序,如果成功连接mysql,则会显示 Success!
二、在docker容器ubuntu系统内使用C/C++连接宿主机的mysql
注意:请保证宿主机已安装mysql服务器,并开启服务。
1. 编写makefile
# 第一步,增加特权用户 mysql -u root -p # 进入mysql,回车后需要输入root密码 # 下面在mysql交互里修改root用户的可访问地址 grant all privileges on *.* to 'testuser'@'%' identified by '123456'; flush privileges; exit; # testuser是新建的用户名,其密码是123456 # '%' 允许访问数据库的IP地址,%意思是任意IP,也可以指定IP # flush privileges 刷新权限信息 # 第二步,允许外网连接mysql服务器 vim /etc/mysql/mysql.conf.d/mysqld.cnf # 找到 bind-address = 127.0.0.1 这一行,注释掉(行首加#) ②宿主机是windows(宿主机操作) 一步:创建允许外网访问的特权用户。 # 请使用管理员权限运行cmd # 进入到mysql的安装目录里的/bin/目录下,再执行: .\mysql -uroot -p #进入mysql交互 # 下面在mysql交互里修改root用户的可访问地址 grant all privileges on *.* to 'testuser'@'%' identified by '123456'; flush privileges; exit; # testuser是新建的用户名,其密码是123456 # '%' 允许访问数据库的IP地址,%意思是任意IP,也可以指定IP # flush privileges 刷新权限信息
2. 运行makefile,生成镜像(最后有个点。myimage是镜像名字,tag是版本号)
$ docker build -t myimage:tag .
3. 生成容器并进入
docker run -it myimage:tag /bin/bash
4. 使宿主机允许docker容器连接mysql服务
缘由分析: 容器内访问localhost是访问容器本身,访问不到宿主机,故先查宿主机ip。容器内执行 ifconfig 可以查看ip:
【未解决的问题】:按说现在可以直接通过ip:172.17.0.1连接宿主机了,但实际测试中总是不行,使用WIFI局域网的ip都连通了,唯独172.17.0.1拒绝访问。恳请知情的大神在评论区指点!
若ifconfig和ping命令不识别,请安装插件:
apt install net-tools # ifconfig apt-get install inetutils-ping # ping apt-get install telnet # telnet
但是默认情况下,宿主机的mysql只允许本地(localhost)访问,docker容器是拒绝访问的。因此需要修改宿主机mysql用户的权限。
①宿主机是ubuntu系统(宿主机操作)
两步,1.创建允许外网访问的特权用户,2.修改mysql配置文件,使其接受外网连接。
# 第一步,增加特权用户 mysql -u root -p # 进入mysql,回车后需要输入root密码 # 下面在mysql交互里修改root用户的可访问地址 grant all privileges on *.* to 'testuser'@'%' identified by '123456'; flush privileges; exit; # testuser是新建的用户名,其密码是123456 # '%' 允许访问数据库的IP地址,%意思是任意IP,也可以指定IP # flush privileges 刷新权限信息 # 第二步,允许外网连接mysql服务器 vim /etc/mysql/mysql.conf.d/mysqld.cnf # 找到 bind-address = 127.0.0.1 这一行,注释掉(行首加#)
②宿主机是windows(宿主机操作)
一步:创建允许外网访问的特权用户。
# 请使用管理员权限运行cmd # 进入到mysql的安装目录里的/bin/目录下,再执行: .\mysql -uroot -p #进入mysql交互 # 下面在mysql交互里修改root用户的可访问地址 grant all privileges on *.* to 'testuser'@'%' identified by '123456'; flush privileges; exit; # testuser是新建的用户名,其密码是123456 # '%' 允许访问数据库的IP地址,%意思是任意IP,也可以指定IP # flush privileges 刷新权限信息
【未解决的问题】:按说现在可以直接通过ip:172.17.0.1连接宿主机了,但实际测试中总是不行,使用WIFI局域网的ip都连通了,唯独172.17.0.1拒绝访问。恳请知情的大神在评论区指点!
5. 在容器内编写C++程序【关注ip与端口】
vim test.cpp #include<stdio.h> #include<mysql/mysql.h> const char *db_host="localhost"; const char *db_user="root"; const char *db_pass="rootroot"; const char *db_name="mydatabase"; const int db_port=3306; int main () { MYSQL *mysql=mysql_init(NULL); //初始化数据库连接变量 if(mysql==NULL) { printf("Error:%s\n",mysql_error(mysql)); exit(1); } mysql = mysql_real_connect(mysql,db_host,db_user,db_pass,db_name, db_port,NULL,0); //连接mysql if(mysql) printf("Success!\n"); //连接成功 else printf("Failed!\n"); return 0; }
6. 编译C++程序并执行
g++ test.cpp -o test -lmysqlclient
注:末尾务必加上 -lmysqlclient 否则编译时找不到mysql库
./test
这是执行程序,如果成功连接mysql,则会显示 Success!
三、libmysqlclient-dev库常用函数
示例1
#include<stdio.h> #include<mysql/mysql.h> const char *db_host="172.17.0.1"; const char *db_user="root"; const char *db_pass="rootroot"; const char *db_name="mydatabase"; const int db_port=3306; int main () { MYSQL *mysql=mysql_init(NULL); //初始化数据库连接变量 if(mysql==NULL) { printf("Error:%s\n",mysql_error(mysql)); exit(1); } mysql = mysql_real_connect(mysql,db_host,db_user,db_pass,db_name, db_port,NULL,0); //连接mysql if(mysql) printf("Suucess!\n"); //连接成功 else printf("Failed!\n"); return 0; } 6. 编译C++程序并执行 g++ test.cpp -o test -lmysqlclient 注:末尾务必加上 -lmysqlclient 否则编译时找不到mysql库 ./test 这是执行程序,如果成功连接mysql,则会显示 Success! 三、libmysqlclient-dev库常用函数 示例1 #include <iostream> #include <cstdlib> #include <string> #include <vector> #include <mysql/mysql.h> using namespace std; int main(){ const char *host = "localhost"; const char *user = "root"; const char *upwd = "root"; const char *dbs = "test"; unsigned int port = 3306; MYSQL mydata; if(0==mysql_library_init(0,NULL,NULL)){ cout<<"mysql_library_init() successed!!"<<endl; }else{ cout<<"mysql_library_init() failed!!"<<endl; return -1; } //初始化数据结构 if(NULL != mysql_init(&mydata)){ cout<<"初始化数据结构成功!"<<endl; }else{ cout<<"初始化数据结构失败"<<endl; return -1; } //设置数据库编码类型 if(0==mysql_options(&mydata,MYSQL_SET_CHARSET_NAME,"utf8")){ cout<<"设置数据库编码类型成功!"<<endl; }else{ cout<<"设置数据库编码类型失败!"<<endl; return -1; } //连接数据库 if(NULL != mysql_real_connect(&mydata,host,user,upwd,dbs,port,NULL,0)){ cout<<"数据库连接成功了!"<<endl; }else{ cout<<"数据库连接失败了!!"<<endl; return -1; } //插入数据 //string sqlstr; //sqlstr="INSERT INTO user(`username`, `password`) VALUES ('test', 'test123');"; //if(0==mysql_query(&mydata,sqlstr.c_str())){ // cout<<"插入数据成功"<<endl; //}else{ // cout<<"插入数据失败了!!"<<endl; //} string sqlstr_select = " select * from user;"; //显示查询结果 MYSQL_RES *result=NULL; if(0==mysql_query(&mydata,sqlstr_select.c_str())){ cout<<"查询成功!"<<endl; //一次性取得数据集 result =mysql_store_result(&mydata); //取得并打印行数 my_ulonglong rowcount = mysql_num_rows(result); cout << "row count: " << rowcount << endl; //取得并打印各字段的名称 unsigned int fieldcount = mysql_num_fields(result); MYSQL_FIELD *field = NULL; for (unsigned int i = 0; i < fieldcount; i++) { field = mysql_fetch_field_direct(result, i); cout << field->name << "\t\t"; } cout << endl; ////打印各行 //MYSQL_ROW row = NULL; //row = mysql_fetch_row(result); //while (NULL != row) { // for (int i = 0; i < fieldcount; i++) { // cout << row[i] << "\t\t"; // } // cout << endl; // row = mysql_fetch_row(result); //} }else{ cout << "mysql_query() select data failed" << endl; mysql_close(&mydata); return -1; } mysql_close(&mydata); mysql_library_end(); return 0; }
示例2
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<string.h> #include<time.h> #include<mysql/mysql.h> #include<unistd.h> #include<sys/types.h> #include<sys/wait.h> const char *db_host="192.168.31.16"; const char *db_user="testuser"; const char *db_pass="123456"; const char *db_name="woj"; const int db_port=3306; static MYSQL *mysql; //数据库连接对象 static MYSQL_RES *mysql_res; //sql查询结果 static MYSQL_ROW mysql_row; //sql查询到的单行数据 char sql[256]; //暂存sql语句 void get_wating_solution(int solution_queue[],int &queueing_cnt) //从solution表读取max_running个待判编号 { queueing_cnt=0; sprintf(sql,"SELECT id FROM solution WHERE result<=%d ORDER BY id ASC limit %d",OJ_WT,max_running); if(mysql_real_query(mysql,sql,strlen(sql))!=0){ printf("select failed!\n"); exit(1); } mysql_res=mysql_store_result(mysql); //保存查询结果 char sid_str[max_running*11]="\0"; while(mysql_row=mysql_fetch_row(mysql_res)) //将结果读入判题队列 { solution_queue[queueing_cnt++]=atoi(mysql_row[0]); if(sid_str[0]!='\0')strcat(sid_str,","); strcat(sid_str,mysql_row[0]); } if(queueing_cnt>0) //更新已读入的solution的result { sprintf(sql,"UPDATE solution SET result=%d WHERE id in (%s)",OJ_QI,sid_str); //更新状态 mysql_real_query(mysql,sql,strlen(sql)); } int main () { mysql = mysql_init(NULL); //初始化数据库连接 mysql = mysql_real_connect(mysql,db_host,db_user,db_pass,db_name, db_port,NULL,0); if(!mysql){ printf("Error: Can't connect to database!\n\n"); exit(1); } static int running_cnt=0,queueing_cnt; //排队数 static int solution_queue[max_running]; //队列 get_wating_solution(solution_queue,queueing_cnt); mysql_close(mysql); return 0; }