使用C绑定到IOCP套接字以获取IOCP

时间:2017-04-10 18:51:01

标签: c udp iocp

我试图使用IOCP从本地(环回)应用程序的UDP端口读取。 IOCP适用于TCP / IP,但我无法为UDP正确打开套接字。

这就是我在做的事情:

// same as for tcp/ip
struct sockaddr_in remoteAddr = { 0 };
remoteAddr.sin_addr.s_addr = LOOPBACK_ADDRESS;
remoteAddr.sin_family = AF_INET;
remoteAddr.sin_port = htons(portNumber);

// using SOCK_DGRAM here
SOCKET sock = INVALID_SOCKET;
sock = WSASocketW(AF_INET, SOCK_DGRAM, IPPROTO_IP, 
    NULL, 0, WSA_FLAG_OVERLAPPED);

if( sock == INVALID_SOCKET ) {
    LOG("WSASocketW failed: %d", WSAGetLastError());
    return;
}

nRet = WSAConnect(*sock, (const struct sockaddr*)&remoteAddr, sizeof(remoteAddr),
    NULL, NULL, NULL, NULL);

if (nRet == SOCKET_ERROR)
{
    LOG("WSAConnect failed: %d", WSAGetLastError());
    return;
}

nRet = WSARecv(sock, &wsabuf, 1, NULL, &flags, &overlapped, NULL);
if (nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()))
{
    LOG("WSARecv failed: %d", WSAGetLastError());
    return;
}

// no errors of any kind
LOG("seems good so far");

一切都没有错误,但是工作循环线程中的GetQueuedCompletionStatus永远不会返回。如果我做同样的事情来连接到TCP套接字(基本上只用SOCK_DGRAM替换SOCK_STREAM),我会在循环中获取数据。

我做错了什么?

(顺便说一句)我知道我可以使用WSARecvFrom,但我想尽可能多地从TCP套接字重用代码。即希望,设置所有内容,然后在工作线程内发布WSARecv调用,而不管套接字的类型(WSARecv is supposed to work with UDP properly, AFAIK)。

1 个答案:

答案 0 :(得分:0)

由于@WouterHuysentruit的评论,管理让它工作。

基本上,如果我想使用WSARecv接收UDP数据包,我需要bind。如果我想使用WSASend发送UDP数据包,我需要connect。以下是有效的:

if (port_type == incoming_packets)
{
    // bind to port
    ret = bind(*sock, (const struct sockaddr*)&remoteAddr, sizeof(remoteAddr));
    ...
    WSARecv(...);
}
else
{
    // this can send to a loopback udp port which is bound in 
    // a different application
    ret = WSAConnect(*sock, (const struct sockaddr*)&remoteAddr, sizeof(remoteAddr), ...);
    ...
    WSASend(...);
}

正如其他人所指出的,WSAReceiveFrom / WSASendTo通常是UDP的更好选择,但在这种情况下,我可以透明地使用IOCP支持多种端口类型。