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

如果大家对完成端口不熟悉,请先百度一下,详细的资料很多,这里主要是针对 采用 完成端口的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完成时就可以进行对比确定哪个数据包已经发送成功。

你可能感兴趣的:(Socket通讯 完成端口 怎么实现同时收发)