UNIX TCP回射服务器/客户端(3):使用select模型的服务器
来源:互联网 发布:单片机与嵌入式的关系 编辑:程序博客网 时间:2024/05/17 02:16
《Unix网络编程》这本书附带了许多短小精美的小程序,我在阅读此书的时候,将书上的代码按照自己的理解重写了一遍(大部分是抄书上的),加深一下自己的理解(纯看书太困了,呵呵)。此例子在Ubuntu10.04上测试通过。
PS:程序里使用了包裹函数(首字母是大写的函数)和常量(所有字母都是大写的常量)的声明在my_unp.h文件中,定义在unp_base.c和unp_thread.c中,地址:http://blog.csdn.net/aaa20090987/article/details/8096701
程序简介:这是一个运用select函数进行IO复用的服务器模型。它的原理是:当一个客户端连接上服务器时,服务器就将其连接的fd加入fd_set集合,等到这个连接准备好读或写的时候,就通知程序进行IO操作,与客户端进行数据通信。它是一个经典的IO复用模型,但当同时连接的客户端数量变大时,fd_set集合就变得很大,而每次要时行IO操作时,都要遍历一次这个集合,导致效率降低,所以它现在基本上被EPOLL模型代替了。
上代码:
#include "my_unp.h" int main(void) { int i, maxi, maxfd, listenfd, connfd, sockfd; pid_t childpid; int nready, client[FD_SETSIZE]; ssize_t n; fd_set rset, allset; char buf[MAXLINE]; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; //创建用于TCP协议的套接字 listenfd = Socket(AF_INET, SOCK_STREAM, 0); memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); //把socket和socket地址结构联系起来 Bind(listenfd, (SA*)&servaddr, sizeof(servaddr)); //开始监听LISTENQ端口 Listen(listenfd, LISTENQ); maxfd = listenfd; maxi = -1; //初始化结构fd_set for(i=0; i<FD_SETSIZE; i++) client[i] = -1; FD_ZERO(&allset); FD_SET(listenfd, &allset); while(1) { rset = allset; //阻塞程序,等待某个事件的发生(见注解1) //这里没有对Select函数设置超时,会导致程序有安全隐患 nready = Select(maxfd+1, &rset, NULL, NULL, NULL); //如果监听的套接字变得可读,就建立一个新链接 if( FD_ISSET(listenfd, &rset) ) { clilen = sizeof(cliaddr); //调用accept函数并更新相关的数据结构 connfd = Accept(listenfd, (SA*)&cliaddr, &clilen); //输出客户端的IP地址与端口号,还有处理(子)进程的PID printf("connection from %s, port %d. process with clild %d\n", Inet_ntop(AF_INET, (void*)&cliaddr.sin_addr, buff, sizeof(buff)), ntohs(cliaddr.sin_port), childpid); for(i=0; i<FD_SETSIZE; i++) { if( client[i] < 0 ) { client[i] = connfd; break; } } //链接数已经达到上限了 if( FD_SETSIZE == i ) error_quit("too many clients"); //增加新的描述符到集合中 FD_SET(connfd, &allset); if( connfd > maxfd ) maxfd = connfd; if( i > maxi ) maxi = i; //利用select的返回值来检查末就绪的描述符 if( --nready <= 0 ) continue; } //扫描每个现在客户链接 for(i=0; i<=maxi; i++) { sockfd = client[i]; if( sockfd < 0 ) continue; if( FD_ISSET(sockfd, &rset) ) { n = Read(sockfd, buf, MAXLINE); //如果客户关闭了链接,就更新数据结构 if( 0 == n ) { Close(sockfd); FD_CLR(sockfd, &allset); client[i] = -1; } //否则,就回射一段字符给客户端 else Writen(sockfd, buf, n); } if( --nready <= 0 ) break; } } return 0; }与其配套的客户端在这里:http://blog.csdn.net/aaa20090987/article/details/8462262
- UNIX TCP回射服务器/客户端(3):使用select模型的服务器
- UNIX TCP回射服务器/客户端(4):使用epoll模型的服务器
- UNIX TCP回射服务器/客户端之使用epoll模型的服务器
- UNIX TCP回射服务器/客户端(5):多线程服务器
- UNIX网络编程——使用select函数的TCP和UDP回射服务器程序
- 使用Select I/O模型来实现一个并发处理多个客户端的TCP服务器
- UNIX TCP回射服务器/客户端(1):用于测试的客户端
- 基于select模型的tcp服务器---一个服务器如何与多个客户端进行通信?
- UNIX TCP回射服务器/客户端(2):多进程服务器
- UNIX TCP回射服务器/客户端(6):进程池服务器
- UNIX TCP回射服务器/客户端(6):线程池服务器
- UNIX网络编程学习(15)--使用单进程和select的TCP服务器程序
- 《UNIX网络编程 卷1》 笔记: 使用select函数的单进程TCP回射服务器程序
- 基于select模型的TCP服务器
- tcp服务器(使用select)
- 【Linux网络编程】基于TCP协议 I/O多路转接(select) 的高性能回显服务器客户端模型
- Select I/O模型来实现一个并发处理多个客户端的TCP服务器
- select函数的单进程和TCP回射服务器应用模型
- 一个基于Gstreamer和GTK的Linux下的简单多媒体播放器
- TClientDataSet[23]: 使用数据集字段(TDataSetField)
- PKU 3225
- Hibernate 性能优化
- soj 1564. HOUSING
- UNIX TCP回射服务器/客户端(3):使用select模型的服务器
- DH密钥交换算法
- hibernate的formula .
- TClientDataSet[19]: 查找字段(fkLookup)
- 配置Memcache实现主从复制repcached功能
- html中嵌入flv格式文件的代码
- google面试题目7
- 计算机科学与技术专业双学士课程
- i18n和l10n的意思