0

我正在编写一个音频流媒体(客户端-服务器)作为我的项目(C/C++),我决定为这个项目制作一个多线程 UDP 服务器。

这背后的逻辑是每个客户端都将在他自己的线程中处理。我遇到的问题是线程相互干扰。

我的服务器做的第一件事是创建一种线程池;它创建了 5 个线程,所有这些线程都被一个recvfrom()函数自动阻止,尽管在大多数情况下,当我将另一台设备连接到服务器时,多个线程正在响应,然后导致服务器完全被阻止,并且不再操作。

调试它也很困难,所以我写在这里是为了获得一些关于多线程 UDP 服务器通常如何实现的建议。

我应该在部分代码中使用互斥锁还是信号量?如果有,在哪里?

任何想法都会非常有帮助。

4

4 回答 4

1

退后一步:你说

每个客户都将在自己的线程中处理

但是UDP不是面向连接的。如果所有客户端都使用相同的多播地址,则没有自然的方法来决定哪个线程应该处理给定的数据包。


如果您坚持每个客户端都有自己的线程的想法(我通常会反对,但在这里可能有意义),您需要一些方法来确定每个数据包来自哪个客户端。

这意味着要么

  • 使用 TCP(因为您似乎无论如何都在尝试面向连接的行为)
  • 读取每个数据包,确定它属于哪个逻辑客户端连接,并将其发送到正确的线程。注意,由于路由信息是全局/共享状态,所以这两者是等价的:

    1. 保留源 IP -> 线程映射,受互斥锁保护,从所有线程读取和访问
    2. 在单个线程中执行所有读取,使用本地源 IP -> 线程映射

    第一个似乎是你想要的,但它的设计很糟糕。当一个数据包进来时,你会唤醒一个线程,然后它会锁定互斥体并进行查找,并可能唤醒另一个线程。您要处理此连接的线程也可能被阻塞读取,因此您需要一些机制来唤醒它。

    第二个至少给出了关注点的分离(读取/调度与处理)。


明智地,您的设计应该取决于

  • 客户数量
  • 输入输出负载
  • 非 I/O 处理量(或 IO:CPU 比率,或...)
于 2012-12-27T00:30:47.143 回答
1

我的服务器做的第一件事是创建一种线程池;它创建了 5 个线程,所有这些线程都被 recvfrom() 函数自动阻止,尽管在大多数情况下,当我将另一台设备连接到服务器时,多个线程正在响应,然后导致服务器完全封锁,不再操作

与其让所有线程都位于同一个套接字连接上的 recvfrom() 上,不如使用信号量保护连接,并让工作线程在信号量上等待。当一个线程获取信号量时,它可以调用recvfrom(),当它返回一个数据包时,线程可以释放信号量(让另一个线程获取)并自己处理数据包。完成对数据包的服务后,它可以返回等待信号量。这样您就可以避免在线程之间传输数据。

于 2013-01-02T17:33:58.707 回答
0

您的 recvfrom 应该在主线程中,当它获取数据时,您应该将地址 IP:Port 和 UDP 客户端的数据传递给辅助线程。

每次主线程接收到 UDP 数据包时,可以通过生成一个新线程来传递 IP:端口和数据,或者可以通过消息队列将其传递给辅助线程

于 2012-12-26T13:54:53.590 回答
0

我认为您的主要问题是非持久性 udp 连接。Udp 不会让您的连接保持活动状态,它每个会话只交换两个数据报。根据您的应用程序,在最坏的情况下,它将有并发线程从第一个可用信息中读取,即,即使轮到它,recvfrom() 也会解除阻塞。

我认为要走的路是在主线程中使用 select ,并使用并发缓冲区来管理线程将做什么。在此解决方案中,您可以为每个客户端设置一个线程,或为每个文件设置一个线程,前提是您保留了客户端必要的信息以确保发送正确的文件部分。

TCP 是另一种实现方式,因为它为您运行的每个线程保持连接活动,但不是允许应用程序丢失数据的最佳传输方式。

于 2012-12-26T23:52:25.673 回答