设为首页 加入收藏

TOP

Linux后台网络编程中select/poll/epoll的比较分析(一)
2014-11-24 03:32:22 来源: 作者: 【 】 浏览:0
Tags:Linux 后台 网络编程 select/poll/epoll 比较 分析

select本质是通过设置或检查存放fd标志位的数据结构来进行下一步的处理。会阻塞,直到有一个或多个I/O就绪。


监视的文件描述符分为三类set,每一种对应不同的事件。readfds、writefds和exceptfds是指向描述符集的指针。


readfds列出的文件描述符被监视是否有数据可供读取。(可读)


writefds列出的文件描述符被监视是否有写入操作完成。(可写)


exceptfds列出的文件描述符被监视是否发生异常,或无法控制的数据是否可用。(仅仅用于socket)


这三类set为NULL时,select()不监视其对应的该类事件。


select()成功返回时,每组set都被修改以使它只包含准备好的I/O描述符。


其缺点:(a)单个进程可监视的fd数量被限制;


(b)需要维护一个用来存放大量fd的数据结构,这样会使用户空间和内核空间在传递该结构时复制开销大;


(c)对fd进行扫描是线性的,fd剧增后,IO效率较低,因为每次调用都对fd进行线性扫描遍历,所以随着fd的增加会造成遍历速度慢的性能问题;


(d)内核需要将消息传递用户空间,需要内核拷贝动作;


(e)最大支持1024个fd。


server端代码,文件名为:select-server.c


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


#define MAXBUF 1024
/************关于本文档********************************************
*filename: select-server.c
*purpose: 演示网络异步通讯、select用法,这是服务器端程序
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to: Google.com
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/


int main(int argc, char **argv)
{
int sockfd, new_fd;
socklen_t len;
struct sockaddr_in my_addr, their_addr;
unsigned int myport, lisnum;
char buf[MAXBUF + 1];
fd_set rfds;
struct timeva l tv;
int retval, maxfd = -1;


if (argv[1])
myport = atoi(argv[1]);
else
myport = 7838;


if (argv[2])
lisnum = atoi(argv[2]);
else
lisnum = 2;


if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}


bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(myport);
if (argv[3])
my_addr.sin_addr.s_addr = inet_addr(argv[3]);
else
my_addr.sin_addr.s_addr = INADDR_ANY;


if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))
== -1) {
perror("bind");
exit(1);
}


if (listen(sockfd, lisnum) == -1) {
perror("listen");
exit(1);
}


while (1) {
printf
("\n----等待新的连接到来开始新一轮聊天……\n");
len = sizeof(struct sockaddr);
if ((new_fd =
accept(sockfd, (struct sockaddr *) &their_addr,
&len)) == -1) {
perror("accept");
exit(errno);
} else
printf("server: got connection from %s, port %d, socket %d\n",
inet_ntoa(their_addr.sin_addr),
ntohs(their_addr.sin_port), new_fd);


/* 开始处理每个新连接上的数据收发 */
printf
("\n准备就绪,可以开始聊天了……直接输入消息回车即可发信息给对方\n");
while (1) {
/* 把集合清空 */
FD_ZERO(&rfds);
/* 把标准输入(stdin)句柄0加入到集合中 */
FD_SET(0, &rfds);
maxfd = 0;
/* 把当前连接(socket)句柄new_fd加入到集合中 */
FD_SET(new_fd, &rfds);
if (new_fd > maxfd)
maxfd = new_fd;
/* 设置最大等待时间 */
tv.tv_sec = 1;
tv.tv_usec = 0;
/* 开始等待 */
retval = select(maxfd + 1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
printf("将退出,select出错! %s", strerror(errno));
break;
} else if (retval == 0) {
/* printf
("没有任何消息到来,用户也没有按键,继续等待……\n"); */
continue;
} else {
/*判断当前IO是否是stdin*/
if (FD_ISSET(0, &rfds)) {
/* 用户按键了,则读取用户输入的内容发送出去 */
bzero(buf, MAXBUF + 1);
fgets(buf, MAXBUF, stdin);
if (!strncasecmp(buf, "quit", 4)) {
printf("自己请求终止聊天!\n");
break;
}
len = send(new_fd, buf, st

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Android SearchView 搜索框 下一篇Linux下通过PHP对MySQL中的数据进..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·工业机器人TCP校准中 (2025-12-25 05:19:17)
·opc 通讯协议与 TCP (2025-12-25 05:19:15)
·labview中tcp/ip通信 (2025-12-25 05:19:13)
·新书介绍《Python数 (2025-12-25 04:49:47)
·怎么利用 Python 进 (2025-12-25 04:49:45)