目錄
一、在ubuntu系統中C/C++連接配接mysql
二、在docker容器ubuntu系統内使用C/C++連接配接主控端的mysql
三、libmysqlclient-dev庫常用函數
一、在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++程式中,修改相應的資料庫配置變量!順便建立一個資料庫供後面測試:
mysql -u root -p # 進入mysql資料庫互動
# 下面在mysql互動下執行
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
最新方法:在版本高于18.03的docker中直接通路 `host.docker.internal` 就可以通路到主控端!以下可以不看!
注意:請保證主控端已安裝mysql伺服器,并開啟服務。
1. 編寫makefile
FROM ubuntu:16.04
RUN echo "\
deb http://mirrors.163.com/ubuntu/ bionic main restricted universe multiverse\n\
deb http://mirrors.163.com/ubuntu/ bionic-security main restricted universe multiverse\n\
deb http://mirrors.163.com/ubuntu/ bionic-updates main restricted universe multiverse\n\
deb http://mirrors.163.com/ubuntu/ bionic-proposed main restricted universe multiverse\n\
deb http://mirrors.163.com/ubuntu/ bionic-backports main restricted universe multiverse\n\
deb-src http://mirrors.163.com/ubuntu/ bionic main restricted universe multiverse\n\
deb-src http://mirrors.163.com/ubuntu/ bionic-security main restricted universe multiverse\n\
deb-src http://mirrors.163.com/ubuntu/ bionic-updates main restricted universe multiverse\n\
deb-src http://mirrors.163.com/ubuntu/ bionic-proposed main restricted universe multiverse\n\
deb-src http://mirrors.163.com/ubuntu/ bionic-backports main restricted universe multiverse\n" > /etc/apt/sources.list \
&& apt update\
&& apt install -y g++ libmysqlclient-dev
EXPOSE 80
2. 運作makefile,生成鏡像(最後有個點。myimage是鏡像名字,tag是版本号)
$ docker build -t myimage:tag .
3. 生成容器并進入
docker run -it myimage:tag /bin/bash
4. 使主控端允許docker容器連接配接mysql服務
緣由分析: 容器内通路localhost是通路容器本身,通路不到主控端,故先查主控端ip。容器内執行 ifconfig 可以檢視ip:

圖中 172.17.0.2是指容器本身的ip,那麼主控端的ip就是172.17.0.1。是以在docker内通路主控端的mysql時,就是用這個ip。執行一下 ping 172.17.0.1 或 telnet 172.17.0.1 3306試試能不能通路到主控端。
若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與端口】
#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;
}
3.常用API
mysql_affected_rows() 傳回被最新的UPDATE, DELETE或INSERT查詢影響的行數。
mysql_close() 關閉一個伺服器連接配接。
mysql_connect() 連接配接一個MySQL伺服器。該函數不推薦;使用mysql_real_connect()代替。
mysql_change_user() 改變在一個打開的連接配接上的使用者和資料庫。
mysql_create_db() 建立一個資料庫。該函數不推薦;而使用SQL指令CREATE DATABASE。
mysql_data_seek() 在一個查詢結果集合中搜尋一任意行。
mysql_debug() 用給定字元串做一個DBUG_PUSH。
mysql_drop_db() 抛棄一個資料庫。該函數不推薦;而使用SQL指令DROP DATABASE。
mysql_dump_debug_info() 讓伺服器将調試資訊寫入日志檔案。
mysql_eof() 确定是否已經讀到一個結果集合的最後一行。這功能被反對; mysql_errno()或mysql_error()可以相反被使用。
mysql_errno() 傳回最近被調用的MySQL函數的出錯編号。
mysql_error() 傳回最近被調用的MySQL函數的出錯消息。
mysql_escape_string() 用在SQL語句中的字元串的轉義特殊字元。
mysql_fetch_field() 傳回下一個表字段的類型。
mysql_fetch_field_direct () 傳回一個表字段的類型,給出一個字段編号。
mysql_fetch_fields() 傳回一個所有字段結構的數組。
mysql_fetch_lengths() 傳回目前行中所有列的長度。
mysql_fetch_row() 從結果集合中取得下一行。
mysql_field_seek() 把列光标放在一個指定的列上。
mysql_field_count() 傳回最近查詢的結果列的數量。
mysql_field_tell() 傳回用于最後一個mysql_fetch_field()的字段光标的位置。
mysql_free_result() 釋放一個結果集合使用的記憶體。
mysql_get_client_info() 傳回客戶版本資訊。
mysql_get_host_info() 傳回一個描述連接配接的字元串。
mysql_get_proto_info() 傳回連接配接使用的協定版本。
mysql_get_server_info() 傳回伺服器版本号。
mysql_info() 傳回關于最近執行得查詢的資訊。
mysql_init() 獲得或初始化一個MYSQL結構。
mysql_insert_id() 傳回有前一個查詢為一個AUTO_INCREMENT列生成的ID。
mysql_kill() 殺死一個給定的線程。
mysql_list_dbs() 傳回比對一個簡單的正規表達式的資料庫名。
mysql_list_fields() 傳回比對一個簡單的正規表達式的列名。
mysql_list_processes() 傳回目前伺服器線程的一張表。
mysql_list_tables() 傳回比對一個簡單的正規表達式的表名。
mysql_num_fields() 傳回一個結果集合重的列的數量。
mysql_num_rows() 傳回一個結果集合中的行的數量。
mysql_options() 設定對mysql_connect()的連接配接選項。
mysql_ping() 檢查對伺服器的連接配接是否正在工作,必要時重新連接配接。
mysql_query() 執行指定為一個空結尾的字元串的SQL查詢。
mysql_real_connect() 連接配接一個MySQL伺服器。
mysql_real_query() 執行指定為帶計數的字元串的SQL查詢。
mysql_reload() 告訴伺服器重裝授權表。
mysql_row_seek() 搜尋在結果集合中的行,使用從mysql_row_tell()傳回的值。
mysql_row_tell() 傳回行光标位置。
mysql_select_db() 連接配接一個資料庫。
mysql_shutdown() 關掉資料庫伺服器。
mysql_stat() 傳回作為字元串的伺服器狀态。
mysql_store_result() 檢索一個完整的結果集合給客戶。
mysql_thread_id() 傳回目前線程的ID。
mysql_use_result() 初始化一個一行一行地結果集合的檢索。