gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 12:02:06 25 4
gpt4 key购买 nike

我有两个简单的 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/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com