分享
 
 
 

WinSock I/O系列1:多路复用I/O支持多Client的实现及效率讨论

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

1. 引言

多路复用I/O模型(select)是UNIX/LINUX用得的最多的一种I/O模型,在Windows下也

可做为一种同步I/O使用。本文给出该I/O模型处理多Client的简单(在主线程中)实现。

2. 关于select

select I/O模型是一种异步I/O模型,在单线程中Linux/WinNT默认支持64个客户端套

接字。这种I/O模型主要涉及以下几个函数及宏:

int select(…)、FD_ZERO、FD_SET、FD_ISSET以及FD_SETSIZE。

3. 用select开发一个Server

3.1 只支持单个Client

// 相关初始化处理, 创建监听套接字

listen(listensock, 5);

clientsock = accept(listensock, NULL, NULL);

for (; ;)

{

FD_ZERO(&readfds);

FD_SET(clientsock, &readfds);

nResult = select(

0, // Windows中这个参数忽略,Linux中在此处为1

readfds, // 可读套接字集合

……

)

if (nResult = = SOCKET_ERROR)

return –1;

// 判断cliensock是否处于待读状态

if (FD_ISSET(clientsock, &readfds))

{

// 相关处理

}

}

其实Winsock中的WSAEventSelect模型是与之类似的。

3.2 在单线程中支持63个Client

SOCKET clientsockarray[FD_SETSIZE – 1]; // FD_SETSIZE is 64

// 相关初始化处理, 创建监听套接字

listen(listensock, 5);

// 初始化套接字数组

InitSock(clientsockarray);

FD_ZERO(&readfds);

FD_SET(listensock, &readfds);

for (; ;)

{

nRet = select(0, &readfds, NULL, NULL, NULL);

// 判断监听套接字是否可读

if (FD_ISSET(listensock, &readfds))

{

clientsock = accept(listensock, NULL, NULL);

// 将客户套接字放到套接字数组中

if (!InsertSock(clientsockarray, clientsock))

{

printf("客户端超过了63个,此次连接被拒绝.\n");

closesocket(clientsock);

continue;

}

}

// 逐个处理处于待决状态的套接字

for (nIndex = 0; nIndex < FD_SETSIZE - 1; nIndex++)

{

if (FD_ISSET(clientsockarray[nIndex], &readfds))

{

nRet = recv(clientsockarray[nIndex], buff, sizeof(buff), 0);

if (nRet = = 0 || nRet = = SOCKET_ERROR)

{

closesocket(clientsockarray[nIndex]);

clientsockarray[nIndex] = INVALID_SOCKET;

continue; // 继续处理套接字句柄数组中的其它套接字

}

// 将接受到的数据进行处理,此处只将其输出

printf("%s\n", buff);

}

}

// 初始化套接字集合

FD_ZERO(&readfds);

FD_SET(listensock, &readfds);

// 将所有有效的套接字句柄加入到套接字句柄数组中

for (nIndex = 0; nIndex < FD_SETSIZE - 1; nIndex++)

{

if (clientsockarray[nIndex] != INVALID_SOCKET)

FD_SET(clientsockarray[nIndex], &readfds);

}

}

BOOL InsertSock(SOCKET* pSock, SOCKET sock)

{

for (int nIndex = 0; nIndex < FD_SETSIZE – 1; nIndex++)

{

if (pSock[nIndex] = = INVALID_SOCKET)

{

pSock[nIndex] = sock;

break;

}

}

if (nIndex = = FD_SETSIZE – 1)

return FALSE;

return TRUE;

}

上面只是给简要的代码,有的辅助函数也没有给出。用select支持多Client是比较方便的,在一个线程中可支持63个;可以采用多线程支持更大数量的Client。

4. 效率的讨论

4.1 对套接字数组扫描的效率问题

在上面的程序中,存在多处对套接字句柄的扫描处理,这个肯定会影响效率。不知道各位朋友是怎么处理这个问题的。

4.2 对客户端实时响应问题

上面的程序处理待决的套接字的时候,是逐个处理的,如果响应某个Client的时间长到一定程度的话,肯定会影响对其它客户端的响应。我的解决方法是当这个套接字处于可读的待决状态的话,产生一个子线程去处理------接收数据和处理数据。这样主线程继续自己的工作,其它Client可以得及时的响应;当然当有大量的Client请求时,对线程的控制会成为一个新问题。

在UNIX/LINUX下做一个支持大量Client的Server的话,本人还是最先选择select这种I/O模型,这是因为我还不知道LINUX还有哪些更好的I/O模型。WinNT的话,还有CompletionPort和Overlapped,特别对于有大数据量传送,同时只有少量的Client时,Overlapped可以发挥相当大的作用。各位朋友请给出使用select的好方法。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有