IOCP 服务器的非 IOCP 客户端发送/接收错误
Posted
技术标签:
【中文标题】IOCP 服务器的非 IOCP 客户端发送/接收错误【英文标题】:Non-IOCP client send/recv error with IOCP server 【发布时间】:2015-12-11 09:23:37 【问题描述】:请理解我是 IOCP 新手,我的代码可能不是那么完美。
我尝试了很多这里的例子,但没有一个能帮助我。 我的实际问题在客户端,我不知道我是否正确连接到 IOCP 服务器,如果我正确发送数据并且 recv 给我 WSAerror 10038 ...
WSADATA wsd;
struct addrinfo *result = NULL, *ptr = NULL, hints;
WSAOVERLAPPED RecvOverlapped;
SOCKET ConnSocket = INVALID_SOCKET;
WSABUF DataBuf;
DWORD RecvBytes, Flags;
CRITICAL_SECTION criti;
char buffer[DATA_BUFSIZE];
int err = 0;
int rc;
// Load Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsd);
if (rc != 0)
return 1;
// Make sure the hints struct is zeroed out
SecureZeroMemory((PVOID)& hints, sizeof(struct addrinfo));
// Initialize the hints to retrieve the server address for IPv4
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
rc = getaddrinfo(IP, Port, &hints, &result);
if (rc != 0)
return 1;
for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
if ((ConnSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol)) == INVALID_SOCKET)
freeaddrinfo(result);
return 1;
rc = connect(ConnSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (rc == SOCKET_ERROR)
if (WSAECONNREFUSED == (err = WSAGetLastError()))
closesocket(ConnSocket);
ConnSocket = INVALID_SOCKET;
continue;
freeaddrinfo(result);
closesocket(ConnSocket);
WSACleanup();
return 1;
break;
if (ConnSocket == INVALID_SOCKET)
freeaddrinfo(result);
return 1;
int nZero = 0;
// Make sure the RecvOverlapped struct is zeroed out
SecureZeroMemory((PVOID)& RecvOverlapped, sizeof(WSAOVERLAPPED));
// Create an event handle and setup an overlapped structure.
RecvOverlapped.hEvent = WSACreateEvent();
if (RecvOverlapped.hEvent == NULL)
freeaddrinfo(result);
closesocket(ConnSocket);
return 1;
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
// send data to server here?
// removed the packets, it`s not supposed to be public
// Call WSARecv until the peer closes the connection
// or until an error occurs
while (1)
Flags = 0;
RecvBytes = 0;
rc = WSARecv(ConnSocket, &DataBuf, 1, &RecvBytes, &Flags, &RecvOverlapped, NULL);
if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError())))
closesocket(ConnSocket);
break;
rc = WSAWaitForMultipleEvents(1, &RecvOverlapped.hEvent, TRUE, INFINITE, TRUE);
if (rc == WSA_WAIT_FAILED)
break;
rc = WSAGetOverlappedResult(ConnSocket, &RecvOverlapped, &RecvBytes, FALSE, &Flags);
if (rc == FALSE)
break;
// here I have a protocol where I read the received data
WSAResetEvent(RecvOverlapped.hEvent);
// If 0 bytes are received, the connection was closed
if (RecvBytes == 0)
break;
WSACloseEvent(RecvOverlapped.hEvent);
closesocket(ConnSocket);
freeaddrinfo(result);
WSACleanup();
我希望能够发送数据并接收来自 IOCP 的响应,但是如果我发送 3 个数据包,当我发送 3 个数据包时,我只会收到 2 个或有时甚至 1 个。 有人可以向我展示一个将数据连接并发送+接收数据到 IOCP 服务器的工作示例吗?
非常感谢!
【问题讨论】:
【参考方案1】:您正在使用 TCP。 TCP 是 stream 协议,而不是数据报协议。你不能告诉它要发送什么数据包,它不能告诉你它收到了什么数据包(它甚至不知道,因为这是在 IP 层处理的)。就是这样不行。
这句话充满智慧:“TCP 是一种双向、面向连接的字节流协议,它提供可靠、有序的传递,但不保留应用程序消息边界。”将“TCP”输入您最喜欢的搜索引擎并进行研究,直到您准确理解该句子中每个单词的含义。除非您这样做,否则您永远不会编写可靠甚至正确的 TCP 代码。
服务器是否使用 IOCP 或其他一些内部架构对客户端没有影响。那是完全看不见的。
【讨论】:
以上是关于IOCP 服务器的非 IOCP 客户端发送/接收错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 IOCP 的 TCP/IP 服务器。接收缓冲区中的偶尔数据损坏