gpt4 book ai didi

multithreading - 如何将单个端口用于多个逻辑数据流(Winsock)?

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

我正在开发客户端-服务器 Winsock 应用程序 (Visual C++),它应该通过网络传输各种数据(视频流、音频流、服务通知等)。我知道更简洁的方法是为每个单独的数据类型在单独的线程上使用单独的端口(我在这里称之为“流”)。但这需要占用至少 5 个不同的端口,这对于某些网络基础设施(防火墙端口转发等)会产生问题。

所以我正在尝试实现单端口连接(TCP),只有一个套接字用于传输不同的流。单个数据包将在 header 中包含信息,该信息将表示它属于哪个流、预期的总消息大小等。假设我有 5 个不同的流。我打算用5个线程来调用发送() 同一个 socket 。这安全吗?我知道来自不同流的数据包会混合到达,但如果我在每个发送的数据包中包含必要的元信息,它可以在另一端正确重建,对吧?

但真正的问题是接收端。虽然调用 可能没问题发送() 来自同一个套接字上的多个线程(虽然我不确定,需要您的确认!),调用 接收 () 来自多个线程没有多大意义。所以我应该使用一个阻塞 接收 () 从一个线程。但是,然后,根据数据包 header (识别特定数据包属于哪个流),我应该在不同的线程中 fork 处理。视频流应该由一个线程处理,声音流 - 由另一个线程处理,等等。但我不太清楚如何做到这一点 - 如何从接收线程 fork 数据处理。性能是重中之重,因此不能考虑通过一个线程处理所有流。

所以总结一下,我有三个问题:

  • 可以调用吗发送() 对于来自多个线程的同一个套接字? (假设数据包头中有关于它属于哪个发送者线程(即子系统)的信息)。
  • 拥有一个阻塞 接收端socket,调用接收 () 在单个线程的循环中,如何将接收到的不同逻辑流的数据包“ fork ”到不同的工作线程?
  • 对于通过一个端口实现多流传输,您还有什么建议?

  • P.S.:Afaik,没有办法通过多个套接字使用一个端口,对吗?

    它是 Windows 平台、Winsock2、Visual C++(如果你能提供特定于平台的提示,那就太好了)。

    = 更新 =
  • 当您说“锁定套接字”时,您的意思是对 的访问进行序列化。发送() 功能?例如与 Critical Section ?
  • 至于接收端...我想我会在 时组装消息(我称“消息”为逻辑完整的数据结构,例如视频帧或声音样本等)。接收 () - 将它们循环播放(将来自单个流的消息缓冲到单个缓冲区中),然后我只是将组装的消息(当一个将被完全接收时)传递给 fork 线程。 现在这就是问题 - 如何通过它们。 我想到的一种方法是Event Objects : 设置事件() 从接收线程到触发 WaitForSingleObject() (在某个循环中)在不同的线程中。你能建议这是否是可接受的解决方案吗?你能提出更好的建议吗?没有比事件对象更快的解决方案(“触发”同一应用程序的另一个线程)吗?以及如何传递数据?
  • 最佳答案

    • Is it OK to call send() for same socket from multiple threads? (assuming there will be info in packet header about which sender thread (i.e. subsystem) it belongs).


    当然你可以从多个线程调用它。但请记住,您必须在 synchronize 的套接字上加锁。它。否则,您最终可能会得到写入不一致的信息。

    • Having one blocking socket on the receiving end, calling recv() in loop from a single thread, how to "fork" the received packets of different logical streams to different worker threads?


    写一个类似于 boost asios 的 BeginRecv 和 EndRecv 怎么样?库(或切换到 Boost Asio。它独立于平台!)。当您收到完整的消息后,您可以将其发送出去。我猜你想把它放在其他地方以便继续从网络接收?您可以使用 CreateThread并通过 lpParameter 发送您的数据参数,这将是其他人的问题而不是recv。在下载数据之前 fork 它不会有太大意义,因为您仍然需要在下一个包之前下载完整的包。

    • What would be your additional recommendations for implementing multiple-stream transfer through one port?


    不太了解,但我写过 an answer之前关于 Winsock,我描述了 recv() 的不确定性。不要忘记同步以确保在下一个包之前写入一个包。

    When you say to "lock socket", you mean serialize the access to send() function? e.g. with Critical Section?



    确实是的。你可以通过使用 RAII 来做这件事。对于锁(然后它会在函数返回时自动删除/解锁)。但是,是的,使用 sendData您首先锁定对象然后发送数据的功能。

    Now that is the question - how to pass them.



    好吧,您可以将其作为新线程传递。
    DWORD WINAPI myVideoProcessor(LPVOID theData){
    StructForKeepingVideoData* data = dynamic_cast<StructForKeepingVideoData*>(theData);
    // process the data that is passed in theData
    ...
    }
    ...
    void ReceiveData(){
    while (true){
    ...
    char buffer[SIZE];
    recv(mySocket, buffer, SIZE, 0);
    StructForKeepingVideoData* data = new StructForKeepingVideoData(buffer);

    HANDLE mId = CreateThread(NULL, 0, myVideoProcessor, data, 0, NULL);
    // now, the video processing will be done somewhere else. let's continue receiving data!
    }
    }

    我在这里有点朦胧..但我认为您应该检查诸如 auto_ptr之类的结构或 shared_ptr传输数据时 - 这将帮助您销毁数据。

    The one way I've thought of is Event Objects: SetEvent() from receiver thread to trigger WaitForSingleObject() (which is in some loop) in different threads. Can you advice if this is the acceptable solution?



    事件也会起作用,但这不是我冒险的事情。然后,您将一直保持线程运行,而不是在有数据要处理时启动。
    记住 您还必须保持数据传输同步。如果您有某种队列,则必须确保写入和读取一个接一个地完成。

    Can you suggest anything better? Aren't there any faster solutions to do this ("trigger" another thread of the same application) than Event Objects? And how to pass the data?



    不会知道更快的事情。但是要传递数据,要么在创建线程时进行,要么使用某种保持同步的队列。

    希望这可以帮助。

    关于multithreading - 如何将单个端口用于多个逻辑数据流(Winsock)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6331003/

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