设置套接字的非阻塞模式
来源:互联网 发布:java集合类有什么用 编辑:程序博客网 时间:2024/04/29 08:11
当使用socket()函数和WSASocket()函数创建套接字时,默认都是阻塞的。在创建套接字之后,通过调用ioctlsocket()函数,将该套接字设置为非阻塞模式。函数的第一个参数是套接字,第二个参数设置为FIONBIO,第三个参数设置为unsigned long类型的非零值。下面代码清单演示了如何用ioctlsocket()函数,设置套接字为非阻塞模式。
SOCKET s; //套接字
unsigned long ul = 1; //设置套接字选项
int nRet; //返回值
s = socket(AF_INET, SOCK_STREAM, 0); //创建套接字
nRet = ioctlsocket(s, FIONBIO, (unsigned long*)&ul); //设置套接字非阻塞模式
if (nRet == SOCKET_ERROR)
{
//设置套接字非阻塞模式,失败处理
}
套接字设置为非阻塞模式后,在调用Windows Sockets API函数时,调用函数会立即返回。大多数情况下,这些函数调用都会调用“失败”,并返回WSAEWOULDBLOCK错误代码。说明请求的操作在调用期间内没有时间完成。通常,应用程序需要重复调用该函数,直到获得成功返回代码。下面程序清单示例了一个在非阻塞套接字上反复调用recv()函数,直到收到1024个字节的数据。
#define NUM_REQUIRED 1024 //需要读入数据的大小
#define MAX_SIZE 2048 //输入缓冲区的大小
TCHAR buff[MAX_SIZE]; //输入缓冲区
bool close; //对方关闭了连接
SOCKET sock; //Windows sockets
void ReadData(void)
{
int nTotal = 0; //已经读入缓冲区字节数
int nRead = 0; //在调用recv时实际读入字节数
int nLeft = 0; //剩下数据的字节数
int nBytes = 0; //当前已读数据在缓冲区的位置
nLeft = NUM_REQUIRED;
while (nTotal != NUM_REQUIRED)//已经读入缓冲区的字节数不等于需要读入的大小时
{
nRead = recv(sock, &buff[MAX_SIZE - nBytes], nLeft, 0); //接收数据
if(SOCKET_ERROR == nRead) //读操作失败
{
int err = WSAGetLastError();
if(WSAEWOULDBLOCK == err) //接收数据缓冲区不可用
{
continue; //接着读取数据
}else if(WSAETIMEDOUT == err || WSAENETDOWN == err) //连接已经断开
{
close = TRUE; //函数退出
break;
}
}
if( 0 == nRead) //客户端关闭了连接
{
close = TRUE; //函数退出
break;
}
nTotal += nRead;
nLeft -= nRead;
nBytes += nRead;
}
return;
}
在该程序中,通过调用WSAGetLastError()函数获得recv()函数返回的错误代码。当返回WSAEWOULDBLOCK错误时,说明此时套接字的缓冲区还没有准备好的数据。需要继续调用该函数。
在该程序中,还对recv()函数返回的其他错误代码进行处理。WSAETIMEDOUT和WSAENETDOWN错误说明,此时由于网络系统的原因与对方的连接已经断开了。当函数返回0时,说明对方关闭了连接。在程序中通过设置close布尔变量值为TRUE,表明与对方的连接已经断开。调用break语句跳出while循环体,函数退出。在开发中,应该根据具体情况对函数返回的错误值进行具体处理。
不同的Windows Sockets API函数,在调用失败时返回的WSAEWOULDBLOCK错误代码具有不同的含义。表对几个Windows Sockets API函数返回WSAEWOULDBLOCK错误的含义进行了总结。
表 WSAEWOULDBLOCK的含义
函数名
说明
accept()和WSAAcept()
应用程序没有收到连接请求
recv()、WSARecv()、recvfrom()和WSARecvfrom()
接收缓冲区没有收到数据
send()、WSASend()、sendfrom()和WSASendfrom()
发送缓冲区此时不可用
connect()和WSAConnect()
连接未能立即完成
closescoket()
通常情况下意味着应用程序使用SO_LINGER选项并且设置了一个非零的超时值,调用了setsocketopt()函数
需要说明的是并非所有的Windows Sockets API在非阻塞模式下调用,都会返回WSAEWOULDBLOCK错误。例如,以非阻塞模式的套接字为参数调用bind()函数时,就不会返回该错误代码。当然,在调用WSAStartup()函数时更不会返回该错误代码,因为该函数是应用程序第一调用的函数,当然不会返回这样的错误代码。
要将套接字设置为非阻塞模式,除了使用ioctlsocket()函数之外,还可以使用WSAAsyncselect()和WSAEventselect()函数。当调用该函数时,套接字会自动地设置为非阻塞方式。在后续章节中,讲解该函数的使用方法。
- 设置套接字的非阻塞模式
- 5.1.2 设置套接字的非阻塞模式
- 5.1 套接字的非阻塞模式
- 套接字的非阻塞模式
- 套接字的非阻塞模式
- 套接字的阻塞模式和非阻塞模式
- 设置阻塞或非阻塞套接字
- 设置套接字为非阻塞的方法
- 设置套接字 为 非阻塞
- 4.1.2 设置套接字的阻塞模式
- 非阻塞套接字
- Winsock 套接字的两种模式阻塞和非阻塞
- php的非阻塞套接字socket
- 套接字的阻塞和非阻塞send/recv
- 高级套接字函数 fcntl 设置socket 非阻塞
- 套接字阻塞模式
- 网络编程(七) 正确的设置非阻塞套接字
- 非阻塞套接字用法
- 关于女人 男人应该偷偷知道的十件事情
- 心经
- 修复bad ELF interpreter问题
- Tarena 课程体系
- DX90SDK SDK源码分析(四) DirectShow在VS2005中PVOID64问题和配置问题
- 设置套接字的非阻塞模式
- Linux下配置jdk1.7
- c++ 通过网络模块Socket连接三菱PLC
- SQLite SQL语句结构详解
- php+mysql 留言板
- 女人也绝情——女人不爱你时的10个表现
- 【转】Linux服务器性能评估
- 不成熟女人会做的傻事
- 将现有工程导入到eclipse的方法