您的位置:首页 > 其它

Socket通讯 完成端口 怎么实现同时收发

2015-06-09 10:32 330 查看
如果大家对完成端口不熟悉,请先百度一下,详细的资料很多,这里主要是针对 采用 完成端口的SOCKET如果实现同时异步收发的进阶篇,由于之前在网上查找资料后发现对于这方面的相关资料甚少,于是在此留文。

你需要熟悉如下函数才能理解此文: CreateIoCompletionPort,GetQueuedCompletionStatus,WSARecvForm,WSASendTo

这里是以UDP的通讯为设计前提,TCP的大同小异。

废话少说,直接进主题:

HANDLE WINAPI CreateIoCompletionPort(
_In_     HANDLE    FileHandle,
_In_opt_ HANDLE    ExistingCompletionPort,
_In_     ULONG_PTR CompletionKey,
_In_     DWORD     NumberOfConcurrentThreads
);


完成端口在创建时需要传入CompletionKey,这个Key是在创建时传入的,由用户自定义,(可能指向一个结构体),我们再来看看下面的取结果函数

BOOL WINAPI GetQueuedCompletionStatus(
_In_  HANDLE       CompletionPort,
_Out_ LPDWORD      lpNumberOfBytes,
_Out_ PULONG_PTR   lpCompletionKey,
_Out_ LPOVERLAPPED *lpOverlapped,
_In_  DWORD        dwMilliseconds
);

这个 lpCompletionKey
的函数就是取创建时传入的值,我们可以在里面存放对应的socket地址等数据, 但我们是没办法分清到底是那一次的发送和接收数据完成了(最理想的状态是GetQueuedCompletionStatus函数中能返回我们每一次发送接收的数据包地址),所以造成在网上很多人都是采用单纯的异步接收,而发送只能用同步的方式,在这个基础上我提出一种进阶的方法:

看看这个函数中有一个OverLapped的结构体,经过测试,这个结构体返回的地址刚好就是我们调用 WSARecvForm 或WSASendto中传入的OverLapp的地址

因此只要我们在调用WSASendTo和WSARecvForm时记录下该OverLapp的地址到链表,那样在GetQueuedCompletionStatus完成时就可以进行对比确定哪个数据包已经发送成功。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: