




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Ch7 Unix Programming other programming主要内容主要内容l7.1 并发服务器设计l7.2 数据库编程本章重点本章重点 l并发服务器程序的设计lMySQL数据库的使用lC API函数的介绍以及应用lLinux下MySQL数据库的应用7.1 并发服务器设计并发服务器设计l7.1.1 迭代服务器 l7.1.2 简单并发服务器 单客户单进程l7.1.3 单线程服务器单客户单线程l7.1.4 I/O复用服务器l7.1.5 进程池l7.1.6 线程池7.1.1 迭代服务器迭代服务器l接受一个客户端的连接,然后处理,完成了这个客户的所有请求后,断开连接。TCP循环服务器一
2、次只能处理一个客户端的请求,只有在这个客户的所有请求满足后,服务器才可以继续后面的请求。如果有一个客户端占住服务器不放时,其它的客户机都不能工作了。7.1.1 迭代服务器迭代服务器代码结构代码结构程序代码结构:socket(.);bind(.);listen(.);while(1) accept(.); process(.); close(.);7.1.1 迭代服务器迭代服务器特点特点 在accept之后,就开始在这一个连接连接上的数据收接收,收到之后处理,发送,不再接收新的连接,除非这个连接的处理结束。 优点: 简单。 缺点: 因为只为一个客户端服务,所以不存在并发的可能。 应用: 用在只为
3、一个客户端服务的时候。7.1.1 迭代服务器迭代服务器举例举例例7-0client.c sockfd = socket(AF_INET, SOCK_STREAM, 0) connect(sockfd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr) write(sockfd,buf,strlen(buf); len = read(sockfd,buf,BUFLEN);buflen=0; if(len 0) printf(服务器的系统时间是:%d %sn,len,buf); close(sockfd); 7.1.1 迭代服务器迭代服务器举
4、例举例例7-1server.cint main(void)sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);bind(sock_descriptor, (struct sockaddr*)&sin, sizeof(sin);listen(sock_descriptor, 100) ;while(1) temp_sock_descriptor = accept(sock_descriptor, (struct sockaddr *)&pin, &address_size); recv(temp_sock_descripto
5、r, buf, 16384, 0) ; ticks = time(NULL); snprintf(buf, sizeof(buf), %.24srn, ctime(&ticks); len=write(temp_sock_descriptor, buf, strlen(buf); close(temp_sock_descriptor);7.1.2 简单并发服务器简单并发服务器 单客户单进程单客户单进程 当客户有请求时 ,为每一个客户请求fork一个子进程,一个子进程(线程)处理一个客户端连接请求,父进程监听7.1.2 简单并发服务器简单并发服务器模型模型7.1.2 简单并发服务器简单并
6、发服务器代码结构代码结构socket(.);bind(.);listen(.);while(1) accpet(.); if(fork(.) = 0) process(.); close(.); exit(.); close(.);7.1.2 简单并发服务器简单并发服务器特点特点优点: 编程相对简单,不用考虑线程间的数据同步等。 缺点: 资源消耗大。启动一个进程消耗相对比启动一个线程要消耗大很多,同时在处理很多的连接时候需要启动很多的进程多去处理,这时候对系统来说压力就会比较大。另外系统的进程数限制也需要考虑。应用: 在客户端数据不多的时候使用很方便,比如小于10个客户端。7.1.2 简单并发
7、服务器简单并发服务器举例举例例7-2process.cint main(int argc, char *argv) sockfd = socket(AF_INET, SOCK_STREAM, 0); bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr); listen(sockfd,listnum) ; handle_connect(sockfd); close(sockfd); return 0;7.1.2 简单并发服务器简单并发服务器举例举例static void handle_connect(int soc
8、kfd) while(1) if(newfd = accept(sockfd,(struct sockaddr*) &c_addr, &len) = -1) perror(accept); exit(errno); else if(fork() 0) close(newfd); else handle_request(newfd); 7.1.2 简单并发服务器简单并发服务器举例举例static void handle_request(int newfd) len = read(newfd,buf,BUFLEN); if(len 0) now = time(NULL); spri
9、ntf(buf,%24srn,ctime(&now); send(newfd,buf,strlen(buf),0); close(newfd);7.1.3 单线程服务器单线程服务器l在一个主程序中,接收客户端的连接,当客户端连接到来时,使用pthread_create函数建立一个线程进程客户端的请求处理,分析数据,给出响应等。 7.1.3 单线程服务器单线程服务器模型模型7.1.3 单线程服务器单线程服务器代码结构代码结构程序代码结构:socket(.);bind(.);listen(.);while(1) accpet(.); if(pthread_create(.)!=-1) pr
10、ocess(.); close(.); exit(.); close(.);7.1.3 单线程服务器单线程服务器特点特点l为每个客户连接创建一个线程l优点:l 相对多进程方式,会节约一些资源,会更加高效一些。l缺点:l 相对多进程方式,增加了编程的复杂度,因为需要考虑数据同步和锁保护。另外一个进程中不能启动太多的线程。在Linux系统下线程在系统内部其实就是进程,线程调度按照进程调度的方式去执行的。l应用:l 类似于多进程方式,适用于少量的客户端的时候。7.1.3 单线程服务器单线程服务器举例举例例7-3thread.cint main(int argc, char *argv) sockfd
11、 = socket(AF_INET, SOCK_STREAM, 0) bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr) listen(sockfd,listnum); handle_connect(sockfd); close(sockfd); return 0;7.1.3 单线程服务器单线程服务器举例举例static void handle_connect(int sockfd) pthread_t thread_s; while(1) if(newfd = accept(sockfd,(struct so
12、ckaddr*) &c_addr, &len) 0) pthread_create(&thread_s,NULL,handle_request,(void *)&newfd); 7.1.3 单线程服务器单线程服务器举例举例static void *handle_request(void *argv) len = read(newfd,buf,BUFLEN); if(len 0 ) now = time(NULL); sprintf(buf,%24srn,ctime(&now); send(newfd,buf,strlen(buf),0); close(n
13、ewfd); return NULL;7.1.4 I/O复用服务器复用服务器 lI/ O复用技术是为了解决进程或线程阻塞到某个 I/ O系统调用而出现的技术 ,使进程不阻塞于某个特定的I/ O系统调用。它也可用于并发服务器的设计,常用函数select 或 poll来实现。 7.1.4 I/O复用服务器复用服务器模型模型7.1.4 I/O复用服务器复用服务器代码结构代码结构bind(listenfd);listen(listenfd);FD_ZERO(&allset);FD_SET(listenfd, &allset);for(;) select(.); if (FD_ISSET
14、(listenfd, &rset) clifd = accept(); cliarray = clifd; FD_SET(clifd, &allset); for(;) fd = cliarrayi; if (FD_ISSET(fd , &rset) dosomething(); Select线程线程l 有一个线程专门用于监听端口,accept返回之后就把这个描述符放入 描述符集合 fd中,一个线程用select去轮训描述符集合,在有数据的连接上接收数据,另外一个线程专门发送数据。当然也可以接收和发送用一个线程。描述符可以设置成非阻塞模式,也可以设置成阻塞模式。通常连接
15、设置成非阻塞模式,发送线程独立出来。l优点:l 相对前几种模式,这种模式大大提高了并发量。l缺点:l 系统一般实现描述符集合是采用一个大数组,每次调用select的时候都会轮询这个描述符数组,当连接数很多的时候就会导致效率下降。连接数在1000以上时候效率会下降到不能接受。l应用:l 目前windows 和一般的Unix上的tcp并发都采用select方式,应该说应用还是很广泛的。7.1.4 I/O复用服务器复用服务器举例举例例7-4IO_multiplex.cint main(int argc, char *argv) sockfd = socket(AF_INET, SOCK_STREAM
16、, 0) bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr); listen(sockfd,listnum) ; pthread_create(&thread_s0,NULL,handle_connect,(void *)&sockfd); pthread_create(&thread_s1,NULL,handle_request, NULL); for(i = 0; i 0) for(i = 0; i CLIENTNUM; i+) if(connect_hosti = -1) conn
17、ect_hosti = newfd; /*客户端计数器*/ connect_num+; /*继续等待新的客户端*/ break; return NULL;7.1.4 I/O复用服务器复用服务器举例举例static void *handle_request(void *argv) int maxfd = -1; fd_set rfds; struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; while(1) FD_ZERO(&rfds); for(i = 0; i CLIENTNUM; i+) if(connect_hosti != -1)
18、FD_SET(connect_hosti,&rfds); if(maxfd connect_hosti) maxfd = connect_hosti; 7.1.4 I/O复用服务器复用服务器举例举例 err = select(maxfd+1, &rfds, NULL, NULL, &tv); switch(err) case 0: break; case -1: break; default: if (connect_num 0) break; for(i = 0; i 0) send(connect_hosti,buf,strlen(buf),0); close(co
19、nnect_hosti); connect_hosti = -1; connect_num-; break; return NULL;7.1.5 进程池进程池l进程池l方法:在服务器端,主程序提前构建多个子进程,当客户端的请求到来的时候,系统从进程池中选取一个子进程来处理客户端的连接,每个子进程处理一个客户端的请求。具体模型为如下: 7.1.5 进程池进程池模型模型7.1.5 进程池进程池举例举例例7-5process_poll.cint main(int argc, char *argv) sockfd = socket(AF_INET, SOCK_STREAM, 0) bind(sockf
20、d, (struct sockaddr*) &s_addr,sizeof(struct sockaddr); listen(sockfd,listnum) int i = 0; for(i = 0; i 0) now = time(NULL); send(newfd,buf,strlen(buf),0); close(newfd); 7.1.6 线程池线程池l线程池l使用预先分配线程的并发服务器与之前使用预先分配进程的并发服务器的主要过程是一致的。主程序先建立多个处理线程,然后等待线程的结束,在多个线程中对客户端的请求进行处理。处理过程包括接收客户端的链接,处理数据,发送响应过程。这个
21、可以结合线程池来进行相应的处理工作。 7.1.6 线程池线程池模型模型7.1.6 线程池线程池举例举例例7-6thread_poll.cint main(int argc, char *argv) sockfd = socket(AF_INET, SOCK_STREAM, 0); bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr) ; listen(sockfd,listnum) ; for(i = 0; i THREADNUM; i+) pthread_create(&thread_si,NULL,h
22、andle_thread,(void *)&sockfd); for(i = 0; i 0) now = time(NULL); send(newfd,buf,strlen(buf),0); close(newfd); return NULL;7.2 MySQL数据库数据库l安装l基本操作l常用API函数l综合应用7.2.0 Linux环境下数据库简介环境下数据库简介lLinux上的主要数据库包括:l商业数据库: Oracle、Sybase、DB2、Informix;l自由软件数据库: MySQL、PostgreSQL、Msql等。mysql数据数据 lMySQL的优点:qMySQL用
23、C和C+编写,可以工作在Unix,Linux,Windows平台上,提供了针对不同编程语言(C,C+,JAVA等)的API函数;q使用核心线程实现多线程,能够很好的支持多CPU;q提供事务和非事务的存储机制;q快速的基于线程的内存分配系统;qMySQL采用双重许可,用户可以在GNU许可条款下以免费软件或开放源码软件的方式使用MySQL软件,也可以从MySQL AB公司获得正式的商业许可。在UNIX 这样的操作系统上,MySQL是免费的,可从因特网上下载其服务器和客户机软件。7.2.1 mysql 安装安装lUbuntu11.10下网络安装sudo apt-get updatesudo apt-
24、get install mysql-serversudo apt-get install mysql-clientsudo apt-get install libmysqlclient-devContentsl安装l基本操作l常用API函数l综合应用7.2.2 mysql基本操作基本操作lmysql的主目录l/var/lib/mysqllmysql的启动/停止/重启lservice mysqld startlservice mysqld stoplservice mysqld restart7.2.2 mysql的基本操作的基本操作l例7.2.1:创建一个数据库rsglxt,在此数据库中新建一
25、个员工信息表employees,表中的字段如表所示。查看employees表中字段的含义,向employees表添加几条记录,查看表中已经存在的记录。 MySQL的使用的使用l操作步骤:操作步骤:步骤步骤 1: 启动启动mysqld,并以,并以root帐号登录帐号登录MySQL。rootlocalhost root#service mysqld startrootlocalhost root# mysql -u root -p 步骤步骤2: 浏览其中已经存在的数据库。 mysqlshow databases; 步骤步骤3: 创建一个名为rsglxt的数据库。 mysqlcreate datab
26、ase rsglxt; 步骤步骤4: 选中数据库rsglxt。 mysqluse rsglxt;password:mydbsql7.2.2 MySQL的使用的使用步骤步骤5: 在rsglxt数据库中新建一个员工信息表employees。 mysqlcreate table employees ( -ID varchar(4) NOT NULL, -username varchar(8), -sex char(2), -age int(2), -card varchar(20), -phone varchar(10), -depID char(2), -position varchar(20),
27、 -primary key (ID);步骤步骤6: 查看employees表中字段的定义。 mysqldescribe employees;7.2.2 MySQL的使用的使用 步骤步骤7: 向employees表添加几条记录。mysql insert into employees values (-0001,张三,男,3485245691,东,职员);mysql insert into employees values (-0002,李四,女,2995175346,西,职员);mysql insert into e
28、mployees values (-0003,虞凡,男,2595175325,西,职员);7.2.2 MySQL的使用的使用 步骤步骤8: 查看表及其中所存在的记录。 mysqlshow tables; mysqlselect * from employees; 步骤步骤9: 退出MySQL客户端。 mysqlexitContentsl安装l基本操作l常用API函数l综合应用7.2.3 常用常用API函数简介函数简介 7.2.3.1 C API数据类型数据类型7.2.3.2 C API函数l数据库的一些常用函数(数据库的一些常用函数(1):l例例7-7c
29、onnect.c: 编写一个程序,实现的功能:测试程序是否连接到数据库rsglxt,如连接成功则显示“数据库连接成功!”,失败则显示出错的原因。7.2.3.2 C API函数l#includel#includelint main() MYSQL com_6_1; mysql_init(&com_6_1); if(!mysql_real_connect(&com_6_1,localhost,root,mydbsql,rsglxt,0,NULL,0) fprintf(stderr,连接数据库失败: %sn,mysql_error(&com_6_1); else printf
30、(数据库连接成功!n); mysql_close(&com_6_1); 注意:编译时加上注意:编译时加上 lmysqlclient7.2.3.2 C API函数l数据库的一些常用函数(数据库的一些常用函数(2):l例例7-8insert.c 通过SQL语句对数据表进行插入操作,对rsglxt数据库中employees表插入一条记录: (0004,王西,男,24 86428462,东,主任)。7.2.3.2 C API函数#include#includeint main() MYSQL com_6_2; char *cr =insert into
31、employees values (0005,王西,男,24, 86428462,na,主任); mysql_init(&com_6_2);if(!mysql_real_connect(&com_6_2,localhost,root,mydbsql,rsglxt,0,NULL,0) fprintf(stderr, 连接数据库失败:%sn,mysql_error(&com_6_2);if(mysql_query(&com_6_2,cr) fprintf(stderr,查询失败:%sn,mysql_error(&com
32、_6_2);else printf(插入记录成功.n,mysql_affected_rows(&com_6_2);mysql_close(&com_6_2);7.2.3.2 C API函数l数据库的一些常用函数(数据库的一些常用函数(3):l例例7-9query.c 连接数据库rsglxt,是否成功给出提示;成功后进行查询,显示数据表employees中的内容。7.2.3.2 C API函数int main() MYSQL com_6_3; MYSQL_RES *ls; MYSQL_ROW hs; char *cxnr; int xht; mysql_init(&com
33、_6_3); /*初始化句柄初始化句柄*/ if(!mysql_real_connect(&com_6_3,localhost,root,mydbsql,rsglxt,0,NULL,0) printf(连接数据库失败连接数据库失败:%sn,mysql_error(&com_6_3); else printf(连接数据库成功连接数据库成功!n); cxnr=select * from employees order by ID asc; xht=mysql_real_query(&com_6_3,cxnr,(unsigned int)strlen(cxnr); if(xh
34、t) printf(查询失败查询失败:%sn,mysql_error(&com_6_3);else printf(查询成功查询成功!n); ls=mysql_use_result(&com_6_3); while(hs=mysql_fetch_row(ls) /*检索一个结果的下一行检索一个结果的下一行*/ for(xht=0;xhtmysql_num_fields(ls);xht+) printf(%s ,hsxht); printf(n); mysql_close(&com_6_3); 7.2.3.2 C API函数l数据库的一些常用函数(数据库的一些常用函数(4)
35、:l例7-10creatdb.c 创建并选择数据库exp。#include#includeint main() MYSQL com_6_4;mysql_init(&com_6_4);if(!mysql_real_connect(&com_6_4,localhost,root,mydbsql,0,NULL,0) printf(连接数据库失败连接数据库失败:%sn,mysql_error(&com_6_4);else printf(连接数据库成功连接数据库成功!n);if(mysql_query(&com_6_4,create database exp)=0)pri
36、ntf(数据库创建成功数据库创建成功!n);else printf(创建数据库失败创建数据库失败:%sn,mysql_error(&com_6_4);if(mysql_select_db(&com_6_4,exp)=0)printf(数据库选择成功数据库选择成功!n);else printf(选择数据库失败选择数据库失败:%sn,mysql_error(&com_6_4);mysql_close(&com_6_4);7.2.3.2 C API函数l数据库的一些常用函数(数据库的一些常用函数(5):l例7-11fetch.c 连接已经创建的 rsglxt数据库中的
37、表employees表,并将记录行定位在第三条,将列光标定位到第三列,之后,显示各字段名及其长度。int main() MYSQL com_6_5;MYSQL_RES *jg; MYSQL_FIELD *zd; MYSQL_ROW hs,hs1; unsigned long *changdu;/*定义字段长度标识定义字段长度标识*/ unsigned int zds;/*定义字段数标识定义字段数标识*/ unsigned int xhl,dw; mysql_init(&com_6_5);if(!mysql_real_connect(&com_6_5,localhost,root,mydbsql,rsglxt,0,NULL,0)printf(数据库连接失败数据库连接失败:%sn,mysql_error(&com_6_5);else printf(数据库连接成功数据库连接成功!n); if(mysql_query(&com_6_5,select * fr
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 叙永县选调事业单位工作人员考试真题2024
- 2024年保山市中医医院招聘真题
- 智慧城市公共服务与可持续发展战略的结合
- 商业策略制定中的心理学策略
- 企业能源管理中的智能电网系统优化
- 教育心理学视角下的学习风格差异与教学策略
- 绿色出行补贴方案考核试卷
- 色散补偿技术考核试卷
- 信用数据服务产业链价值链分析考核试卷
- 自动化在信用合作社风险管理中的预测分析功能考核试卷
- 2025年护士实践能力考试练习题库(附答案)
- 心理咨询师考试练习试题
- 药品安全科普知识课件下载
- 防腐质量管理制度
- 2025年中国商业银行同业业务行业深度分析、投资前景及发展趋势预测报告(智研咨询)
- 环境管理标准化手册
- DB12T 1315-2024城市内涝气象风险等级
- 面向隐私保护联邦学习的激励机制
- 2025年1月南美客车需求近况交流-2025-01-商用车
- 供电所安全文化建设
- 2025年内蒙农信社信息科技专业技术人才社会招聘30人管理单位笔试遴选500模拟题附带答案详解
评论
0/150
提交评论