Windows Sockets编程(三)操作模式1
来源:互联网 发布:小站托福有mac版吗 编辑:程序博客网 时间:2024/06/07 22:06
1、Windows Sockets API的3种操作模式:阻塞的、非阻塞的、异步的。
类比:设想你拨通了一个电话,但是对方这会不在电话旁,此时你的选择可以是:
不挂机,等待,直到对方过来接电话。
挂机,之后再打过去。
留言,让对方打过来。
1)不挂机,等待:阻塞
此模式下,Windows Sockets函数只有当操作完成时才返回,结果可能成功,也可能失败,这样能创建的应用程序就是有局限性的。比如当一个阻塞式调用没有完成时,你不能在任务(或线程)中调用任何其他的WinSock函数,你要接收消息就会成为问题。
2)挂机后再拨:非阻塞
在操作完成过程中需要“探询”,但太频繁会浪费系统资源。此模式下WInSock函数立即返回,有些情况下返回值表示成功,但又是却表示失败。但函数调用并非全是坏事,错误值(调用WSAGetLastError)有可能是WSAEWOULDBLOCK,即“如果必须等待操作完成才能返回,那么函数应该阻塞猜对”。
其有两种含义:一是操作还在等待中,二是WInSock做了尝试,但在当前无法满足操作请求。前者时操作总要完成,并有方法来检测操作是否完成。后者时表示用户还需要再次调用函数。
3)请求对方回拨:异步
此模式是非阻塞的,因为它在操作完成之前就从调用返回了。此时WSAEWOULDBLOCK的含义是:当一个等待处理的操作完成时,或者当重新发起一个操作时,WINSock DLL将发送一个消息(即对方回拨你)来通知你。
建议选择异步操作模式!
一、非阻塞模式
1、无论涉及的操作是否完成,一个非阻塞模式的函数调用都立即返回。大多数非阻塞模式的应用程序都是混合式的,通过采用非阻塞socket和阻塞的select函数来更有效的复用多个socket。
2、函数socket调用所返回的socket句柄在I/O操作时默认是阻塞的。应用程序可以隐式地或显式的将socket变为非阻塞的。如果调用WSAAsyncSelect(),能够自动地使socket变为非阻塞的。其等同于采用异步操作模式。
为了显式的将socket设为非阻塞的,可以调用设置了FIONBIO命令的ioctlsocket()函数。
3、非阻塞函数调用失败时返回一个错误代码,该代码指示成功或当前的socket状态。另一些函数调用可能看起来成功了,但却并没有完成所请求的操作。
1)WSAEWOULDBLOCK错误:
如果一个函数调用失败,WSAGetLastError()返回的此错误,那么这个函数调用并没有失败。根据函数的不同,此错误说明WInSock DLL已经开始了此操作,或者说明你需要稍后再次调用该函数。
2)部分成功:
即使非阻塞socket函数的返回值表明成功,也不意味着确实完成了所要求的操作。例如,函数send、sendto、recv和recvfrom的返回值有可能小于你在输入参数中传递的长度值。所以此时,不仅需要检查成功与否,还要将返回值与你请求传输的数据长度进行比较。
4、探询而非阻塞:
检测何时开始一个操作、当函数失败并返回WSAEWOULDBLOCK后,检测操作是否完成。
5、显式地避让:
Windows Socket的阻塞操作具有隐含的避让机制。非阻塞操作却能够阻塞系统。
解决方案之一是:建立混合式的应用程序,此时只有当检测当前socket状态时采用阻塞的select()函数,其余的操作全用非阻塞socket。之二是创建自己的阻塞钩子函数,可以按照要求进行避让。
二、异步模式
1、窗口是对象,对象是不透明的,其内部细节隐藏在背后。对象之间通过传递消息来通信,而消息是异步到达的,对象则对消息进行响应。Windows Socket的异步操作模式利用Windows的消息机制而非回调机制。
通过采用异步操作模式,应用程序可以把工作“卸载”下来给WInSock DLL去处理,利用Windows的消息驱动架构而不是简单的去对付他。
2、异步函数及其描述:
WSAAsyncGetHostByAddr():根据主机地址检索主机信息
WSAAsyncGetHostByName():根据主机名检索主机信息
WSAAsyncGetProtoByName():根据协议名检索协议号
WSAAsyncGetProtoByNumber():根据协议号检索协议名
WSAAsyncGetServByPort():根据端口号检索服务信息。
WSAAsyncSelect():请求WINSock DLL通知应用程序一个或多个“事件”,诸如连续完成、输出缓存区可用,以及数据到达
3、WSAAsyncGetXByY()
其代表的是异步数据库函数,无论外形还是实际操作都很相似。
HANDLE PASCAL FAR WSAAsyncGetHostByName(
HWND hWnd,
unsigned int wMsg,
char FAR *name,
char FAR *buf,
int buflen);
除了需要解析的对象外,异步的数据库函数(用于主机名、协议和服务解析)都带有一个Windows句柄、一个消息和作为输入参数的一个缓存。这些函数能够在操作完成之前立即返回,返回值是一个能够唯一识别该查询的句柄(这样就能与响应匹配),如果在处理请求时出错,则返回0值。
4、上述操作过程总结如下:
1)应用程序发送解析请求,等待通知解析事件。
2)函数返回一个查询句柄,如果不能处理查询时返回0。
3)查询完成时,WInSock DLL给应用程序发送一个消息,指示解析成功或失败。
5、除了请求对一个或多个事件的异步通知外,WSAAsyncSelect()还自动地把socket设为非阻塞模式,并且不返回句柄(socket就是句柄)。
6、撤销异步操作:
任何WSAAsyncGetXByY()函数发起的异步操作,都可以使用WSACancelAsyncRequest()来撤销。但不能撤销WSAAsyncSelect函数发起的异步操作。
int PASCAL FAR WSACancelAsyncRequest(
HANDLE hAsyncTaskHandle);
参数为将撤销的异步操作的句柄,即由WSAAsyncGetXByY()调用返回的。
成功时返回0值,失败时返回SOCKET_ERROR。常见的是WSAEINVAL(句柄不可用)和WSAEALREADY(异步操作已经撤销)。
7、如果应用程序异步操作正在等待处理时调用WSACleanup(),该异步操作将被撤销(并不发送任何通知)。
8、三种模式总结比较:
非阻塞模式是最快的,但开销最大,也是最不友好的。
异步操作能够很快地传输数据并且同时保持友好性。
阻塞模式是最友好的,但相对较慢。
- Windows Sockets编程(三)操作模式1
- Windows Sockets编程(三)操作模式2
- Windows sockets 网络编程(三)— 非阻塞模式开发
- Windows Sockets 网络编程(三)
- Windows Sockets 网络编程(三)
- Windows Socket 网络编程(三) —— Windows Sockets程序设计
- Windows Socket 网络编程(三) —— Windows Sockets程序设计
- Windows Socket 网络编程(三) —— Windows Sockets程序设计
- Windows Sockets网络编程(1)TCP select & thread
- Windows Sockets 网络编程(三) —— WINDOWS SOCKETS 1.1 程序设计
- 转:Windows Sockets 网络编程(三) —— WINDOWS SOCKETS 1.1 程序设计
- Windows Sockets 网络编程(三) —— WINDOWS SOCKETS 1.1 程序设计
- Windows Sockets 网络编程(三) —— WINDOWS SOCKETS 1.1 程序设
- Java Socket编程(三)服务器Sockets
- Java Socket编程(三) 服务器Sockets
- Windows Sockets:操作顺序
- Windows sockets 网络编程(1) — 综述
- Windows sockets 网络编程(1) — 综述 .
- 汇编语言 HelloWorld (详细注释版)
- 驱动
- readline/readline.h: No such file or directory
- LoG算子
- 去除序号(正则表达式with sublime text)
- Windows Sockets编程(三)操作模式1
- wireshark在win8.1上抓包的问题解决
- 图像处理中各种边缘检测的微分算子简单比较(Sobel,Robert, Prewitt,Laplacian,Canny) 【转】
- llvm vs gcc 我被雷到了, 速度相差300多倍,你还用GCC吗!【转】
- LLVM每日谈之一 LLVM是什么
- override(C# 参考)
- SVM支持向量机,我用到的自学材料
- RapidMiner tuts
- 交?叉?验?证?(?分?类?器?性?能?)