非阻塞模式开发

来源:互联网 发布:unity模型优化 编辑:程序博客网 时间:2024/06/05 09:42

接字的非阻塞模式是指套接字在执行操作时,调用的函数不管操作是否完成都会立即返回的工作模式。非阻塞套接字在处理同时建立的多个连接,发送和接收的数据量不均,时间不定等方面具有明显的优势。但这种套接字在使用上存在一定难度。本章讲述套接字的非阻塞模式及其一个远程算数运算套接字程序。

套接字的非阻塞模式

所有windows平台都支持套接字以阻塞模式和非阻塞模式的方式工作。

非阻塞模式

把套接字设置为非阻塞模式,即通知系统内核:在调用WindowsSocketsAPI时,不要让线程随眠,而应该让函数理解返回。在返回时,该函数返回一个错误代码。一个非阻塞模式套接字多次调用recv()的过程如上。前3次调用recv()函数时,内核函数还没有准备好。因此,该函数理解返回WSAEWOULDBLOCK错误代码。第4次调用recv()函数时,数据已经准备好,被负责到应用程序的缓冲区中,recv()返回成功指示,应用程序开始处理数据。

设置套接字的非阻塞模式

当使用socket(),WSASocket()创建套接字时,默认都是阻塞的。在创建套接字之后,通过调用ioctlsocket(),将该套接字设置为非阻塞模式。

套接字设置为非阻塞模式后,在调用WindowsSocketsAPI函数时,调用函数会立即返回。大多数情况下,这些函数调用都会调用“失败”,并返回WSAEWOULDBLOCK错误代码。说明请求的操作在调用期间内没有时间完成。通常,应用程序需要重复调用该函数,直到获得成功返回代码。

WSAEWOULDBLOCK的含义

函数名

说明

accept(),WSAAcept()

应用程序没有接收到连接请求

recv(),WSARecv(),recvfrom(),WSARecvfrom()

接收缓冲区没有收到数据

send(),WSASend(),sendto(),WSASendto()

发送缓冲区此时不可用

connect(),WSAConnect()

连接未能立即完成

closesocket()

通常情况下意味着应用程序使用SO_LINGER选项并且设置一个非零的超时值,调用了setsocketopt()

需要说明的是并非所有的WindowsSocketsAPI在非阻塞模式下调用,都会返回WSEWOULDBLOCK错误。eg:bind(),listen()

要将套接字设置为非阻塞模式,除了使用ioctlsocket()函数之外,还可以使用WSAAsyncSelect()(7章讲解)WSAEventselect()(8章讲解)。当调用该函数时,套接字会自动地设置为非阻塞方式。

非阻塞模式套接字的优势和不足 

由于使用非阻塞套接字在调用函数时,会经常返回WSAEWOULDBLOCK错误。所以在任何时候,都应仔细检查返回代码,并做好应对“失败”的准备。应用程序连续不断的调用这个函数,直到它返回成功指示为止。本章程序清单中,在While循环体内不断的调用recv(),以读入1024个字节的数据。这种做法很浪费系统资源。

有人使用MSG_PEEK标志调用recv()查看缓冲区中是否有数据可读。同样,这种方法也不好,因为该做法对系统造成的开销是很大的,并且应用程序至少要调用recv()两次,才能实际地读入数据。较好的做法是,使用套接字的“I/O模型”(6,7,8,9,10章来讲解)来判断非阻塞套接字是否可读可写。

非阻塞模式套接字与阻塞套接字相比,使用较复杂。使用非阻塞模式套接字,需要编写更多的代码,以便在每个WindowsSocketAPI函数调用中,对收到的WSAEWOULDBLOCK错误进行处理。因此,非阻塞套接字便显得有些难于使用。

但是,非阻塞套接字在控制建立的多个连接,在数据的收发量不均,时间不定等方面,明显具有优势。通常情况下,可考虑使用套接字的“I/O模型”,它有助于应用程序通过异步方法,同时对一个或多个套接字的通信加以管理。

0 0
原创粉丝点击