jpe*_*pen 5 c++ sockets iocp winsock2
根据MSDN:
hEvent:如果在没有I/O完成例程(操作的lpCompletionRoutine参数设置为null)的情况下发出重叠I/O操作,则此参数应包含WSAEVENT对象的有效句柄或为null.
当我使用IOCP时,当我调用WSASend()或WSARecv()时,我将NULL传递给它们的最后一个参数(即lpCompletionRoutine):
WSASend(pIoRequest->GetSocket(), pIoRequest->GetWsaBuffer(), 1, NULL, pIoRequest->GetFlags(), pIoRequest, NULL);
WSARecv(pIoRequest->GetSocket(), pIoRequest->GetWsaBuffer(), 1, NULL, &(pIoRequest->GetFlags()), pIoRequest, NULL);
Run Code Online (Sandbox Code Playgroud)
我的"每个I/O数据"类(pIoRequest)看起来像:
class IoRequest : public WSAOVERLAPPED
{
public:
IoRequest()
{
...
SecureZeroMemory(this, sizeof(WSAOVERLAPPED));
hEvent = WSACreateEvent(); // A
}
...
void ResetForNextIoRequest()
{
WSACloseEvent(hEvent); // B
SecureZeroMemory(this, sizeof(WSAOVERLAPPED));
hEvent = WSACreateEvent(); // C
...
}
...
DWORD& GetFlags() { return m_dwFlags; }
...
private:
...
DWORD m_dwFlags;
...
};
Run Code Online (Sandbox Code Playgroud)
即使我注释掉上面标记为A,B和C的行,它似乎对我的程序的行为没有任何影响.
那么如何决定何时调用WSACreateEvent()或者只是将hEvent设置为NULL?
Amb*_*jak 16
如果您正在使用IOCP,则无需传递事件对象,因为您将使用GetQueuedCompletionStatus()接收完成通知.假设您已使用CreateIoCompletionPort()将套接字与完成端口相关联,这将起作用.
是的,Windows上的I/O令人困惑.特别是,至少有六种不同的方式来使用套接字.首先,你似乎遇到过两个:
使用IOCP重叠I/O(CreateIoCompletionPort,GetQueuedCompletionStatus,WSASend等).这可能是最有效的方法.您可以轻松地将任何类型的事件也集成到事件循环中,这些事件也使用IOCP.对于其他事件,您可以使用PostQueuedCompletionStatus解决方法.这是(AFAIK)唯一可以扩展大量套接字的方法.
没有IOCP的重叠I/O,即使用WSASend和朋友使用事件对象,使用例如WaitForMultipleObjects监视事件,并使用WSAGetOverlappedResult获取结果.这可以相对容易地与任何非套接字I/O集成,也可以映射到HANDLE对象.但是,WaitForMultipleObjects限制为一次监视不超过64个句柄.
还至少还有四个:
阻止调用(send,recv以及WSA*版本).如果你这样做,你就不得不使用线程.这既难以正确实施又可能效率低下.
使用select()的非阻塞套接字.这样做的好处是可以使用与类Unix系统类似的代码.但是,它(AFAIK)不能与插槽以外的I/O集成.
使用WSAEventSelect进行非阻塞.这与select()方法类似,不同之处在于,不是使用select()来获取通知,而是将套接字事件映射到事件对象,并使用例如WaitForMultipleObjects监视那些事件对象.它也类似于没有IOCP方法的重叠,并且受到不超过64个对象的相同限制.
使用WSAAsyncSelect进行非阻塞.这使用Windows消息循环将套接字通知作为消息传递到程序中的窗口.这很容易集成到已经使用消息循环的应用程序中,例如许多GUI应用程序.
如果我遗漏了一些东西,或者如果其中一些实际上不起作用,请纠正我:).
| 归档时间: |
|
| 查看次数: |
1626 次 |
| 最近记录: |