Linux应用程序开发中的线程池与MySQL综合应用

1.实验目的

安装MySQL数据库,并在数据库中创建‘用户表’,存储至少3条‘用户信息’;

(2)服务器端创建线程池,响应客户端发送的连接请求(请求中包含‘用户信息’中的id或者学号),并将查询到的用户数据返回给客户端;

(3)客户端向服务器端发送连接请求(请求中包含‘用户信息’中的id或者学号),与服务器端建立通信连接,并把服务器端返回的完整‘用户信息’展示在终端上;

(4)至少启动3个客户端,并与服务器端建立连接,可以通过启动3个‘终端’来模拟3个客户端。

2.实验内容

2.1  linux文件解压缩应用

使用  tar  命令解压,方法如下:

将.tgz文件解压在当前目录:

tar zxvf  MY_NAME.tgz

 

将.tar.gz文件解压在当前目录:

tar zxvf  MY_NAME.tar.gz

tar -xvf file.tar //解压 tar包

2.2  Vi/Vim编辑器的使用

1.vi/vim介绍

①vi是Visual Interface的缩写,即 可视化接口

②vim是vi iMprove的缩写,即 vi的增强版(具有语法着色功能)

2.vim模式使用说明

①三种模式

   命令模式(默认):刚进入vim的时候,默认就是 命令模式,可以复制行,删除行等。

   输入模式:可以输入内容。

   末行模式:在最下边,除编辑模式,可以输入诸多管理员命令

②模式转换

   命令模式→输入模式:

i:在当前光标所在字符的前面,转为输入模式

I:在当前光标所在行的行首转换为输入模式

a:在当前光标所在字符的后面,转为输入模式

A:在光标所在行的行尾,转换为输入模式

o:在当前光标所在行的下方,新建一行,并转为输入模式

O:在当前光标所在行的上方,新建一行,并转为输入模式

s:删除光标所在字符

r:替换光标处字符

   输入模式→命令模式

ESC键

   命令模式→末行模式

     输入:即可 转为末行模式

 末行模式-操作

末行模式→命令模式

ESC键    

3.关闭文件

  末行模式下: 

w:保存

q:退出

wq 或 x:保存退出,wq 和 x 都是保存退出

q!:强制退出

w!:强制保存,管理员才有权限

  命令模式下:

ZZ:保存并退出

2.3  MySQL数据库软件的安装、配置及调试

1.检测系统是否已经安装过mysql或其依赖,若已装过要先将其删除,否则第4步使用yum安装时会报错:

# yum list installed | grep mysql   //查看依赖

# yum -y remove mysql-libs.i686  //删除依赖

2.从mysql的官网下载mysql57-community-release-el6-5.noarch.rpm(注意这里的el6-5即适配RHEL6.5的版本,如果下载了其它版本后面的安装过程中可能会报错):

#wget dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm

3.安装第一步下载的rpm文件:

#yum install mysql-community-release-el6-5.noarch.rpm

4.使用yum安装mysql:

#yum install mysql-community-server

5.启动mysql服务:

#service mysqld start

查看root密码:

 # grep "password" /var/log/mysqld.log

现在必须立刻修改密码,不然会报错:

mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpass');

6.修改字符集为UTF-8:

#vim /etc/my.cnf

在[mysqld]部分添加:

character-set-server=utf8

7.特殊情况

编译开发时报错,无法找到lib文件时:

在64位系统中,/usr/lib/mysql/下的相关库文件无法标识,需要将

/usr/lib64/mysql 下的库来做个软链接

# ln -sf /usr/lib64/mysql/libmysqlclient.so /usr/lib/mysql/libmysqlclient.so

# ln -sf /usr/lib64/mysql/libmysqlclient.a /usr/lib/mysql/libmysqlclient.a  

还需要使用yum 安装mysql 支持库mysql-devel

#yum install mysql-devel

2.4  Linux网络通信配置

1.ifcfg-ethn网络配置文件

 

所有的网络接口配置文件均存放在/etc/sysconfig/network-scripts目录下

如系统的第一个以太网接口的配置文件为:

/etc/sysconfig/network-scripts/ifcfg-eth0

2.netconfig网络配置工具

netconfig 运行在字符界面下,可以方便的进行网络配置。

使用netconfig完成网络配置后,只是修改了相应的网络配置文件,并没有使新的属性生效,所以要立即重新启动网络服务。

执行命令:

#service network restart //重启网络服务

netconfig默认配置网卡eth0,若需要配置其他网卡,则:

#netconfig --device eth1 //配置指定的网卡

2.5  基于线程池的客户端与服务端网络通信

经典的在同一台主机上两个进程或线程之间的通信通过以下三种方法

管道通信(Pipes)

消息队列(Message queues)

共享内存通信(Shared memory)

3.实验环境

3.1操作系统平台

实验及相关操作采用在Windows平台中安装Linux虚拟机的方式进行,所需软件如下:

VMware Workstation虚拟机软件;

CentOS6操作系统。

3.2所需软件

自带终端软件;

gcc,g++等开发工具

MySQL5.6版本。

 

4实验步骤

4.1  数据库环境搭建

4.1.1安装MySQL数据库

1.检测系统是否已经安装过mysql或其依赖,若已装过要先将其删除,否则第4步使用yum安装时会报错:

# yum list installed | grep mysql   //查看依赖

# yum -y remove mysql-libs.i686  //删除依赖

#yum install mysql-community-release-el6-5.noarch.rpm

 

2.使用yum安装mysql:

#yum install mysql-community-server

3.启动mysql服务:

#service mysqld start

查看root密码:

 # grep "password" /var/log/mysqld.log

现在必须立刻修改密码,不然会报错:

mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpass');

4.特殊情况

编译开发时报错,无法找到lib文件时:

在64位系统中,/usr/lib/mysql/下的相关库文件无法标识,需要将

/usr/lib64/mysql 下的库来做个软链接

# ln -sf /usr/lib64/mysql/libmysqlclient.so /usr/lib/mysql/libmysqlclient.so

# ln -sf /usr/lib64/mysql/libmysqlclient.a /usr/lib/mysql/libmysqlclient.a  

还需要使用yum 安装mysql 支持库mysql-devel

#yum search mysql

#yum install mysql-devel

4.1.2数据库插入用户信息

1.创建数据库(database)

create database db_test;

2.创建user用户表

create table user( 
    -> id SMALLINT UNSIGNED not null auto_increment,
    ->  name varchar(20) not null, 
    -> stu_no int not null, 
    -> grade varchar(10) , 
    -> class varchar(10), 
    -> course varchar(10),
    -> score int, 
    -> PRIMARY KEY (id) );

3.插入用户数据

mysql> insert into user(id,name,stu_no,grade,class,course,score)
    -> VALUES(1001,'sfx',2016110628,'3','5','linux','99');
Query OK, 1 row affected (0.01 sec)

mysql> insert into user(id,name,stu_no,grade,class,course,score)
    -> VALUES(1002,'sfx1',2016110629,'3','5','linux','97');
Query OK, 1 row affected (0.01 sec)

mysql> insert into user(id,name,stu_no,grade,class,course,score)
    -> VALUES(1003,'sfx2',2016110630,'3','5','linux','98');

 

4.2  客户端编程

vim tcp_client_fork.cpp

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
#define PORT  8890
#define BUFFER_SIZE 1024
 
int main(int argc, char **argv)
{
    if(argc!=2)
    {
        printf("usage: client IP \n");
        exit(0);
    }
 
    //定义IPV4的TCP连接的套接字描述符
    int sock_cli = socket(AF_INET,SOCK_STREAM, 0);
 
    //定义sockaddr_in
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);
    servaddr.sin_port = htons(PORT);  //服务器端口
 
    //连接服务器,成功返回0,错误返回-1
    if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
    {
        perror("connect");
        exit(1);
    }
    printf("connect server(IP:%s).\n",argv[1]);
	printf("service start >>>>>> [ok]\n");
	printf("input ID you want to query>>>\n");
 
    char sendbuf[BUFFER_SIZE];
    char recvbuf[BUFFER_SIZE];
    //客户端将控制台输入的信息发送给服务器端,服务器原样返回信息
    while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
    {
        send(sock_cli, sendbuf, strlen(sendbuf),0); ///发送
        if(strcmp(sendbuf,"exit\n")==0)
        {
            printf("client exited.\n");
            break;
        }
        printf("client receive:\n");
		printf("This is you want to found information >>>\n ");
        recv(sock_cli, recvbuf, sizeof(recvbuf),0); ///接收
        fputs(recvbuf, stdout);
 
        memset(sendbuf, 0, sizeof(sendbuf));
        memset(recvbuf, 0, sizeof(recvbuf));
    }
 
    close(sock_cli);
    return 0;
}

4.3  服务端编程

vim tcp_server_fork.cpp

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include

#define HOSTNAME "localhost"
#define USERNAME "root"
#define PASSWORD "666666"
#define DATABASE "db_test"

 
#define PORT  8890
#define QUEUE_SIZE   10
#define BUFFER_SIZE 1024



//传进来的sockfd,就是互相建立好连接之后的socket文件描述符
//通过这个sockfd,可以完成 [服务端]<--->[客户端] 互相收发数据
void str_echo(int sockfd)
{
    char buffer[BUFFER_SIZE];
    pid_t pid = getpid();
    while(1)
    {
        memset(buffer,0,sizeof(buffer));
        int len = recv(sockfd, buffer, sizeof(buffer),0);
        if(strcmp(buffer,"exit\n")==0)
        {
            printf("child process: %d exited.\n",pid);
            break;
        }
        printf("pid:%d receive:\n",pid);
        fputs(buffer, stdout);
		
		MYSQL conn;
		MYSQL_RES *res;
		MYSQL_ROW row;
		mysql_init(&conn);
		//connect database
	if(!mysql_real_connect(&conn,HOSTNAME,USERNAME,PASSWORD,DATABASE,0,NULL,0)){
			printf("Error connecting to database:%s\n",mysql_error(&conn));
		} 
		else{
			printf("connecting Success >>>>>>\n");
		}
		
		char id[5];
		id[0]=buffer[0];
		id[1]=buffer[1];
		id[2]=buffer[2];
		id[3]=buffer[3];
		printf("id -> %s\n",id);
		char select_id[100];
		sprintf(select_id,"select * from user where id = '%s' ;",id);
		mysql_query(&conn,select_id);
		res = mysql_store_result(&conn);
		while(row = mysql_fetch_row(res))
		{		char information[26];

information[0]=row[0][0];
information[1]=row[0][1];
information[2]=row[0][2];
information[3]=row[0][3];
information[4]=row[1][0];
information[5]=row[1][1];
information[6]=row[1][2];
information[7]=row[1][3];
information[8]=row[2][0];
information[9]=row[2][1];
information[10]=row[2][2];
information[11]=row[2][3];
information[12]=row[2][4];
information[13]=row[2][5];
information[14]=row[2][6];
information[15]=row[2][7];
information[16]=row[2][8];
information[17]=row[3][0];
information[18]=row[4][0];
information[19]=row[5][0];
information[20]=row[5][1];
information[21]=row[5][2];
information[22]=row[5][3];
information[23]=row[5][4];
information[24]=row[6][0];
information[25]=row[6][1];
				for(int a = 0;a<26;a++)
				{
				buffer[a]=information[a];
				}
printf("buffer->'%s'",buffer);
				

		
					
			
				
				printf("\n");
		}
		
		mysql_close(&conn);
		
		
		
        send(sockfd, buffer, len, 0);
    }
    close(sockfd);
}
 
int main(int argc, char **argv)
{
	//connect DATABASE
	//void connectDb();
 	//ConnectDb();
    //定义IPV4的TCP连接的套接字描述符
    int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);
 
    //定义sockaddr_in
    struct sockaddr_in server_sockaddr;
    server_sockaddr.sin_family = AF_INET;
    server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_sockaddr.sin_port = htons(PORT);
 
    //bind成功返回0,出错返回-1
    if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)
    {
        perror("bind");
        exit(1);//1为异常退出
    }
    printf("bind success.\n");
 
    //listen成功返回0,出错返回-1,允许同时帧听的连接数为QUEUE_SIZE
    if(listen(server_sockfd,QUEUE_SIZE) == -1)
    {
        perror("listen");
        exit(1);
    }
    printf("listen success.\n");
 
    for(;;)
    {
        struct sockaddr_in client_addr;
        socklen_t length = sizeof(client_addr);
        //进程阻塞在accept上,成功返回非负描述字,出错返回-1
        int conn = accept(server_sockfd, (struct sockaddr*)&client_addr,&length);
        if(conn<0)
        {
            perror("connect");
            exit(1);
        }
        printf("new client accepted.\n");
 
        pid_t childid;
        if(childid=fork()==0)//子进程
        {
            printf("child process: %d created.\n", getpid());
            close(server_sockfd);//在子进程中关闭监听
            str_echo(conn);//处理监听的连接
            exit(0);
        }
    }
 
    printf("closed.\n");
    close(server_sockfd);
    return 0;
}

 

 

4.4  同时启动测试

1.编译测试

编译客户端

#g++ -o tcpclient tcp_client_fork.cpp

运行时需要指定本地ip

#./tcpclient

Linux应用程序开发中的线程池与MySQL综合应用_第1张图片

编译服务端

需要连接mysql.h 及MySQL的库文件

#g++ -o tcpservice tcp_server_fork.cpp -I /usr/include/mysql -L /usr/lib64/mysql -lmysqlclient

运行./

#./tcpsservice

Linux应用程序开发中的线程池与MySQL综合应用_第2张图片

同时启动3个客户端

1.打开四个终端,第一个开启服务端,其余开启客户端。

如图,(从左至右,从上至下)第一个终端开启了服务端,其余为客户端。

打开服务端,服务端开始监听是否有客户端连接,当有连接时,服务端捕获并将数据显示。

打开客户端时,向服务端请求连接,连接成功时返回信息。

Linux应用程序开发中的线程池与MySQL综合应用_第3张图片

 

客户端向服务端发送想要查询的用户的id (图中红线表示),

服务端将信息返回给客户端(图中蓝线表示)

Linux应用程序开发中的线程池与MySQL综合应用_第4张图片

查看表的信息。

Linux应用程序开发中的线程池与MySQL综合应用_第5张图片

 

用户退出,服务器断开连接。

Linux应用程序开发中的线程池与MySQL综合应用_第6张图片

5实验总结

本次实验是在window平台安装VMware虚拟机上的centos6.0操作系统上完成的,需要了解Linux的基本操作命令,才能进行相关实验操作。此外还需要搭建实验环境,需要安装MySQL数据库、MySQL支持库和g++编译器。此次实验涉及的知识较多,包含数据库的操作,网络通信的操作, 线程池的处理等。

安装MySQL数据库,并在数据库中创建用户表,存储用户信息;服务器端创建线程池,响应客户端发送的连接请求,并将查询到的用户数据返回给客户端;

客户端向服务器端发送连接请求,与服务器端建立通信连接,并把服务器端返回的完整用户信息展示在终端上;启动3个客户端,并与服务器端建立连接,可以通过启动3个‘终端’来模拟3个客户端。这些操作都需要耐心地按部就班的完成。

你可能感兴趣的:(linux)