c++ - 为什么调用 WSASocket() vs socket() 会导致发送阻塞?

标签 c++ windows sockets tcp winsock

我有两个简单的 TCPConnection 和 TCPListener 包装类。使用这些类的应用程序在 Windows 10 上运行并执行以下操作:

  • 线程 1
  • 调用 getaddrinfo、socket、bind、listen、accept 和阻塞等待连接
  • 建立连接后,客户端套接字被传递给第二个线程以发送
  • 开始阻塞 recv() 循环

  • 线程 2
  • 等待排队发送数据
  • 当队列中有可用数据时调用 send()


  • 当我使用 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/

    相关文章:

    c# - 为什么通过TCP发送后字节序颠倒了

    c++ - SWIG 无法识别字符串参数

    c++ - 用于读取通用磁盘格式设备或文件的 C/C++ 库

    c++ - 错误 C2059 : syntax error : '.'

    c++ - CFileDialog 在 Windows XP 下保留目录句柄

    windows - 如何查看 Windows 库 (*.lib) 的内容

    windows - 文件大小 - 磁盘上实际使用的字节数(未分配)

    linux - 如何在 Ubuntu 16.04 中访问 BitLocker 加密的驱动器?

    java - 将套接字复制到另一个套接字,同一个套接字是否仍处于 Activity 状态? java

    python-3.x - 如何将我的 Kivy 客户端连接到服务器(TCP、套接字)