/*
* 1. 編譯環境
* 作業系統 Ubuntu10.04
* GCC 4.4.3
* 首先請確保你的系統安裝了下列軟體包:
* 1. mysql-client,libmysqlclient-dev和libmysqlclient15off
* sudo apt-get install mysql-client libmysqlclient-dev libmysqlclient15off
* ps:若提示找不到libmysqlclient15off,請在軟體源中添加
* deb http://security.ubuntu.com/ubuntu hardy-security main
* 2. mysql-server
* sudo apt-get install mysql-server
*
* 2. 使用前,先在mysql中建立資料庫batman: create database batman;
* 在batman中建立兩張表:TCPpackets, UDPpackets
* create table UDPpackets(MB double,KbperSec double,seconds double,percents double);
* create table TCPpackets(MB double,KbperSec double);
*
* 3. 編譯選項:
* gcc -o c_mysql ./c_mysql.c -I /usr/include/mysql -L /usr/lib/mysql -l mysqlclient -std=c99
*
* 4. 使用方法:
* ./c_mysql <filename> -tcp|-udp
*/
源檔案c_mysql.c的內容如下:
#if defined(_WIN32) || defined(_WIN64) //為了支援windows平台上的編譯#include <windows.h>#endif#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include <mysql.h> //我的機器上該檔案在/usr/include/mysql下//定義資料庫操作的宏,也可以不定義留著後面直接寫進代碼#define INSERT_UDP "insert into UDPpackets values(%f,%f,%f,%f);"#define INSERT_TCP "insert into TCPpackets values(%f,%f);"//input file type#define TCP_DATA 1#define UDP_DATA 2typedef struct _UDPData{ double MB; double KbperSec; double seconds; double percents;}UDPData, *pUDPData;typedef struct _TCPData{ double MB; double KbperSec;}TCPData,*pTCPData;int readLine(FILE* fd, char* buf){ char c; c = fgetc(fd); while(c != '\n' && c != EOF) { *(buf++) = c; c = fgetc(fd); } *buf = '\0'; if(c == EOF) return EOF; else return 0;}void paresUDPRow(char* buf, pUDPData pudp){ int index = 0,strIndex = 0; char str[20]; char *model[] = {"sec","MBytes","Kbits/sec","("}; double dd[4]; for(int i=0; i<4; i++) { index = strstr(buf,model[i]) - buf; index += strlen(model[i]); while( buf[index] == ' ') index++; strIndex = 0; while( isdigit(buf[index]) || buf[index] == '.' ) { str[strIndex++] = buf[index++]; } str[strIndex] = 0; dd[i] = atof(str); } pudp->MB = dd[0]; pudp->KbperSec = dd[1]; pudp->seconds = dd[2]; pudp->percents = dd[3];}void paresTCPRow(char* buf, pTCPData ptcp){ int index = 0,strIndex = 0; char str[20]; char *model[] = {"sec","MBytes"}; double dd[2]; for(int i=0; i<2; i++) { index = strstr(buf,model[i]) - buf; index += strlen(model[i]); while( buf[index] == ' ') index++; strIndex = 0; while( isdigit(buf[index]) || buf[index] == '.' ) { str[strIndex++] = buf[index++]; } str[strIndex] = 0; dd[i] = atof(str); } ptcp->MB = dd[0]; ptcp->KbperSec = dd[1];}int main(int argc, char **argv) //char **argv 相當於 char *argv[]{ MYSQL mysql,*sock; //定義資料庫連接的控制代碼,它被用於幾乎所有的MySQL函數 MYSQL_RES *res; //查詢結果集,結構類型 char buf[256]; char qbuf[256]; //存放查詢sql語句字串 char * filename = NULL; int fileType = TCP_DATA; FILE* fudp; UDPData udp; TCPData tcp; if (argc != 3) { //檢查輸入參數 fprintf(stderr,"usage : ./c_mysql <filename> -tcp|-udp\n\n"); exit(1); } filename = argv[1]; if(strcmp(argv[2],"-tcp")!=0 && strcmp(argv[2],"-udp")!=0) { fprintf(stderr,"usage : ./c_mysql <filename> -tcp|-udp\n\n"); exit(EXIT_FAILURE); } fileType = !strcmp(argv[2],"-udp") ? UDP_DATA : TCP_DATA; mysql_init(&mysql); if (!(sock = mysql_real_connect(&mysql,"localhost","root","123456","batman",0,NULL,0))) { fprintf(stderr,"Couldn't connect to engine!\n%s\n\n",mysql_error(&mysql)); perror(""); exit(1); } fudp = fopen(filename,"r"); if(fudp == NULL) { fprintf(stderr,"Couldn't open file %s\n\n",filename); exit(1); } while(readLine(fudp,buf) != EOF) { if(fileType == UDP_DATA) { paresUDPRow(buf,&udp); sprintf(qbuf, INSERT_UDP, udp.MB, udp.KbperSec, udp.seconds, udp.percents); } else { paresTCPRow(buf,&tcp); sprintf(qbuf,INSERT_TCP,tcp.MB,tcp.KbperSec); } fprintf(stdout,qbuf); fprintf(stdout,"\n"); res = mysql_query(sock,qbuf); if( res ) { fprintf(stderr,"Update failed (%s)\n",mysql_error(sock)); exit(1); } } mysql_close(sock); fclose(fudp); exit(0); return 0; //. 為了相容大部分的編譯器加入此行}
上述代碼的主要作用是把測試batman協議的結果資料儲存到MySQL中,結果包括對TCP測試的結果和對UDP測試的結果。這兩種資料的格式如下:
TCP:
[ 4] 0.0-24.9 sec 2.22 MBytes 747 Kbits/sec[ 5] 0.0-1576.9 sec 125 MBytes 665 Kbits/sec[ 4] 0.0-33.6 sec 2.00 MBytes 499 Kbits/sec[ 5] 0.0-11.9 sec 1.05 MBytes 735 Kbits/sec[ 4] 0.0-26.7 sec 1.98 MBytes 621 Kbits/sec[ 5] 0.0-23.1 sec 1.76 MBytes 638 Kbits/sec
UDP:
[ 3] 0.0-20.6 sec 2.08 MBytes 850 Kbits/sec 43.392 ms 36/ 1521 (2.4%)[ 4] 0.0-20.9 sec 2.13 MBytes 853 Kbits/sec 45.070 ms 0/ 1517 (0%)[ 3] 0.0-20.5 sec 1.80 MBytes 734 Kbits/sec 41.463 ms 9021/10302 (88%)[ 4] 0.0-20.9 sec 2.13 MBytes 855 Kbits/sec 41.880 ms 0/ 1517 (0%)[ 3] 0.0-20.6 sec 2.13 MBytes 869 Kbits/sec 12.608 ms 0/ 1521 (0%)[ 4] 0.0-20.8 sec 2.13 MBytes 857 Kbits/sec 41.295 ms 0/ 1517 (0%)[ 3] 0.0-733.7 sec 15.4 MBytes 176 Kbits/sec 359.811 ms 2913/13907 (21%)[ 4] 0.0-10.3 sec 1.00 MBytes 818 Kbits/sec 22.526 ms 0/ 713 (0%)[ 3] 0.0-34.1 sec 2.00 MBytes 493 Kbits/sec 3.466 ms 0/ 1427 (0%)[ 4] 0.0-12.2 sec 1.00 MBytes 688 Kbits/sec 84.498 ms 0/ 714 (0%)
這不是重點,重點是對MySQL的操作。可是廢話已經一蘿筐了...
1. 首先是第一個要用到的結構:
MYSQL
該結構代表1個資料庫連接的控制代碼。幾乎所有的MySQL函數均使用它。不應嘗試拷貝MYSQL
結構。不保證這類拷貝結果會有用。在後續的資料庫操作中都要把它作為參數的。
2. 在聲明一個MYSQL類型的變數mysql後,就要首先調用 mysql_init(&mysql); 該函數的原型是:MYSQL *mysql_init(MYSQL *mysql)
描述
分配或初始化與mysql_real_connect()相適應的MYSQL對象。如果mysql是NULL指標,該
函數將分配、初始化、並返回新對象。否則,將初始化對象,並返回對象的地址。如果
mysql_init()分配了新的對象,當調用mysql_close()來關閉串連時,將釋放該對象。
傳回值
初始化的MYSQL*控制代碼。如果無足夠記憶體以分配新的對象,返回NULL。
錯誤
在記憶體不足的情況下,返回NULL。
3. 調用mysql_real_connect來獲得一個串連執行個體。
該函數的原型是:MYSQL *mysql_real_connect(MYSQL *mysql,
const char *host,
const char *user,
const char *passwd,
const char *db,
unsigned int port,
const char *unix_socket,
unsigned long client_flag)
描述
mysql_real_connect()嘗試與運行在主機上的MySQL資料庫引擎建立串連。在你能夠執行
需要有效MySQL串連控制代碼結構的任何其他API函數之前,mysql_real_connect()必須成功
完成。
參數的指定方式如下:
# 第1個參數應是已有MYSQL結構的地址。調用mysql_real_connect()之前,必須調用
mysql_init()來初始化MYSQL結構。
# “host”的值必須是主機名稱或IP地址。如果“host”是NULL或字串"localhost",串連將被
視為與本地主機的串連。如果作業系統支援通訊端(Unix)或具名管道(Windows),
將使用它們而不是TCP/IP串連到伺服器。
# “user”參數包含使用者的MySQL登入ID。如果“user”是NULL或Null 字元串"",使用者將被視為
目前使用者。在UNIX環境下,它是當前的登入名稱。在Windows ODBC下,必須明確指定
目前使用者名。
# “passwd”參數包含使用者的密碼。如果“passwd”是NULL,僅會對該使用者的(擁有1個空密
碼欄位的)使用者表中的條目進行匹配檢查。這樣,資料庫管理員就能按特定的方式設定
MySQL許可權系統,根據使用者是否擁有指定的密碼,使用者將獲得不同的許可權。
4. 執行增刪改查操作mysql_query:
該函數的原型是:int mysql_query(MYSQL *mysql, const char *query)
描述
# 執行由“Null終結的字串”查詢指向的SQL查詢。正常情況下,字串必須包含1條SQL語
句,而且不應為語句添加終結分號(‘;’)或“\g”。如果允許多語句執行,字串可包含多條
由分號隔開的語句。
# mysql_query()不能用於包含位元據的查詢,應使用mysql_real_query()取而代之
(位元據可能包含字元‘\0’,mysql_query()會將該字元解釋為查詢字串結束)。
# 如果希望瞭解查詢是否應返回結果集,可使用mysql_field_count()進行檢查。
傳回值
如果查詢成功,返回0。如果出現錯誤,返回非0值。
總結:以上只是介紹了本程式要用到的MySQL資料結構和函數,這些介紹都是來自MySQL手冊,
詳細 資訊可以參考MySQL C API。