我有两个简单的 TCPConnection 和 TCPListener 包装类。使用这些类的应用程序在 Windows 10 上运行并执行以下操作:
当我使用 socket() 调用创建服务器套接字时,这非常有效。当我切换到 WSASocket() 调用(非重叠)时,如果有一个挂起的 recv() 或 WSARecv() 调用正在阻塞,则无论 send() 还是 WSASend() 都将阻塞。
我不知道是什么原因造成的。我一直认为,从不同线程在同一个套接字上发送和接收是可以的。
posix 与 WSA 变体之间的底层实现是否存在差异?知道什么可能导致这种行为吗?
调用区别如下:
sock = socket(AF_INET, SOCK_STREAM, IPOROTO_TCP);
sock = WSASocketW(AF_INET, SOCK_STREAM, IPOROTO_TCP, nullptr, 0, 0);
连接客户端来自 Python 3.8.5
最佳答案
使用 WSASocket() 时,您需要传递 WSA_FLAG_OVERLAPPED 标志以获得与调用 socket() 相同的行为。如果没有它,如果 WSARecv() 或 recv() 在另一个线程中被阻止,windows 将阻止您的 WSASend() 或 send() 调用。
我假设如果我通过了 WSA_FLAG_OVERLAPPED 标志,我的所有套接字操作都会重叠(即所有对 WSARecv() 和 WSASend() 的调用都需要一个 OVERLAPPED 结构),但事实并非如此。
正确用法:
sock = WSASocketW(AF_INET, SOCK_STREAM, IPOROTO_TCP, nullptr, 0, WSA_FLAG_OVERLAPPED);
WSABUF buf { bufferLen, bufferPtr};
DWORD bytes = 0;
DWORD flags = 0;
WSARecv(sock, &buf, 1, &bytes, &flags, nullptr, nullptr); // Thread 1
WSASend(sock, &buf, 1, &bytes, 0, nullptr, nullptr); //Thread 2
和做的一样:sock = socket(AF_INET, SOCK_STREAM, IPOROTO_TCP);
recv(sock, bufferPtr, bufferLen, 0); // Thread 1
send(sock, bufferPtr, bufferLen); // Thread 2
在 Windows 上,您只是无法访问 OVERLAPPED 功能。
关于c++ - 为什么调用 WSASocket() vs socket() 会导致发送阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65238091/