Windows操作系统I/O模型—笔记1(select (选择模型))
来源:互联网 发布:数据中心网络设计方案 编辑:程序博客网 时间:2024/06/05 19:24
select函数可在socket编程中使用,是一种异步IO选
择模型,可以解决套接字(listen,bind,accept,recv这
几个函数会死锁)死锁,
以下笔记仅为个人学习中的记录,有错请提出,3Q
█ select 的函数原型如下:
int select
(
(
__in int nfds, //忽略,保持与Berkeley套接字兼容
__in_out fd_set* readfds, //检查可读性,是一个指向fd_set结构体的指针
__in_out fd_set* writefds, //检查可写性,是一个指向fd_set结构体的指针
__in_out fd_set* exceptfds, //例外数据,是一个指向fd_set结构体的指针
__in const struct timeval* timeout, //时间结构体指针
);
在三个参数中(readfds 、writefds 和 exceptfds ),任何两个都可以是空值( NULL);
但是,至少有一个不能为空值!在任何不为空的集合中,必须包含至少一个套接字句柄;
否则, select 函数便没有任何东西可以等待。最后一个参数 timeout 对应的是一个指针,它指向一个timeval 结构,
用于决定select 最多等待 I/O操作完成多久的时间。如 timeout 是一个空指针,那么 select 调用会无限
期地“锁定”或停顿下去,直到至少有一个描述符符合指定的条件后结束。
select 成功完成后,会在 fdset 结构中,返回刚好有未完成的 I/O操作的所有套接字句柄的总量。
若超过 timeval 设定的时间,便会返回0。若 select 调用失败,都会返回 SOCKET_ERROR,
fd_set 结构的定义如下:
typedef struct fd_set
{
{
u_int fd_count;
SOCKET fd_array[FD_SETSIZE];//#define FD_SETSIZE 64 , fd_set 结构中最多只能监视64个套接字。
} fd_set;
fd_set 结构中最多只能监视64个套接字。
fd_set代表着一系列特定套接字的集合。其中, readfds 集合包括符合下述任何一个条件的套接字:
● 有数据可以读入。
● 连接已经关闭、重设或中止。
● 假如已调用了listen,而且一个连接正在建立,那么accept函数调用会成功。
writefds 集合包括符合下述任何一个条件的套接字:
● 有数据可以发出。
● 如果已完成了对一个非锁定连接调用的处理,连接就会成功。
exceptfds 集合包括符合下述任何一个条件的套接字:
● 假如已完成了对一个非锁定连接调用的处理,连接尝试就会失败。
● 有带外(Out-of-band,OOB)数据可供读取。
一下是部分核心源代码:
}
套接字编写(基于TCP协议)
用 select 对套接字进行监视之前,必须将套接字句柄分配给一个fdset的结构集合,
之后再来调用 select,便可知道一个套接字上是否正在发生上述的 I/O 活动。
Winsock 提供了下列宏操作,可用来针对 I/O活动,对 fdset 进行处理与检查:
● FD_CLR(s, *set):从set中删除套接字s。
● FD_ISSET(s, *set):检查s是否set集合的一名成员;如答案是肯定的是,则返回TRUE。
● FD_SET(s, *set):将套接字s加入集合set。
● FD_ZERO( * set):将set初始化成空集合。 可完成用 select 操作一个或多个套接字句柄的全过程:
1) 使用FDZERO宏,初始化一个fdset对象;
2) 使用FDSET宏,将套接字句柄加入到fdset集合中;
3) 调用 select 函数,等待其返回……select 完成后,会返回在所有 fdset 集合中设置的套接字句柄总数,
并对每个集合进行相应的更新。
4) 根据 select的返回值和 FDISSET宏,对 fdset 集合进行检查。
5) 知道了每个集合中“待决”的 I/O操作之后,对 I/O进行处理,
然后返回步骤1 ),继续进行 select 处理。 一下是部分核心源代码:
BOOL SOCKET_Select(SOCKET hSocket, int nTimeOut, BOOL bRead)
{ fd_set fdset;
{ fd_set fdset;
timeval tv;
FD_ZERO(&fdset);
FD_SET(hSocket, &fdset);
nTimeOut = nTimeOut > 1000 ? 1000 : nTimeOut;
tv.tv_sec = 0;
tv.tv_usec = nTimeOut;
int iRet = 0;
if ( bRead ) {
iRet = select(0, &fdset, NULL , NULL, &tv);
}else{
iRet = select(0, NULL , &fdset, NULL, &tv);
}
if(iRet <= 0) {
return FALSE;
} else if (FD_ISSET(hSocket, &fdset)){
return TRUE;
}
return FALSE; }
套接字编写(基于TCP协议)
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );//加载套接字库
if ( err != 0 ) //加载失败
{
return 0;
}
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1)//加载套接字的版本不符合
{
WSACleanup( );//释放加载资源
return 0;
}
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);//创建套接字
SOCKADDR_IN addrSrv;
addrSrv.sin_addr .S_un .S_addr =htonl(INADDR_ANY);
addrSrv.sin_family =AF_INET;
addrSrv.sin_port =htons(6000);
bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//绑定套接字
listen(sockSrv,5);//监听套接字
SOCKADDR_IN addrCilent;
int len=sizeof(SOCKADDR);
while(1)
{
if(SOCKET_Select) //调用SOCKET_Select 函数
{
if(SOCKET_Select) //调用SOCKET_Select 函数
{
SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrCilent,&len);//接受客服端
char sendBuf[100];
sprintf(sendBuf,"Welcome %s to http://www.Alan.com",inet_ntoa(addrCilent.sin_addr));
send(sockConn,sendBuf,strlen(sendBuf)+1,0);//发送数据
char recvBuf[100];
recv(sockConn,recvBuf,100,0);//接受数据
printf("%s\n",recvBuf);
}
}
closesocket(sockConn);//关闭套接字
}
WSACleanup(); //释放套接字库资源- Windows操作系统I/O模型—笔记1(select (选择模型))
- Windows操作系统I/O模型—笔记2(异步选择(WSAAsyncSelect)模型)
- Windows操作系统I/O模型—笔记3(事件选择(WSAEventSelect)模型)
- Windows Socket五种I/O模型(一)——选择模型(Select)
- Windows Socket五种I/O模型(一)——选择模型(Select)
- WinSock 异步I/O模型[1]---选择模型 - select
- WinSock 异步I/O模型[1]---选择模型 - select
- Windows套接字I/O模型之选择(Select)模型
- Windows 套接字I/O 模型(2) 选择(select)模型
- Windows I/O模型之一:Select模型
- Windows socket I/O模型 之 select(1)
- Windows socket I/O模型 之 select(1)
- Windows套接字I/O模型(2) -- Select模型
- Windows Socket I/O模型---Select模型、异步选择、事件选择
- Windows操作系统I/O模型—笔记4(完成端口(Completion Port)模型+线程池技术)
- Socket I/O模型之选择(select)
- Socket I/O模型之选择(select)
- 选择模型:Select(选择)模型是Winsock中最常见的I/O模型
- UVA11478 Halum (差分约束)
- 【deep learning学习笔记】Restricted Boltzmann Machines for Collaborative Filtering
- 跟我一起学Python之三:模块及保存运行
- JDBC连接MySQL数据库及示例
- poj 1159 Palindrome
- Windows操作系统I/O模型—笔记1(select (选择模型))
- Citrix 服务器虚拟化之二十二 桌面虚拟化之Provisioning Services创建标准映像实现无盘部署
- hdu4486 Pen Counts
- ICE通信之IceGrid服务(二)
- Windows操作系统I/O模型—笔记2(异步选择(WSAAsyncSelect)模型)
- PHP 中文字符串截取函数(UTF-8)有效
- php数据类型细节
- 学习python tkinter 写的一个工具界面
- 中国气象局Web Server 地址