实现多线程UDP服务器的问题(线程池?)

时间:2012-12-26 13:30:48

标签: c++ c multithreading udp threadpool

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

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

我的服务器做的第一件事就是创建一种线程池;它创造了5 所有被recvfrom()函数自动阻止的线程, 虽然看起来似乎在我连接另一台设备的大部分时间 到服务器,多个线程正在响应,稍后 这导致服务器被完全阻止而不能进一步运行。

调试这个也很困难,所以我按顺序写这里 获得有关多线程UDP服务器通常实现方式的一些建议。

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

任何想法都会非常有用。

4 个答案:

答案 0 :(得分:1)

退后一步:你说

  

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

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


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

这意味着

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

    1. 保留源IP - >线程映射,受互斥锁保护,读取和放大从所有线程访问
    2. 在单个线程中执行所有读取,使用本地源IP - >线程映射
    3. 第一个似乎是你正在寻找的东西,但它的设计很糟糕。当一个数据包进入时,你将唤醒一个线程,然后它锁定互斥锁并进行查找,并可能唤醒另一个线程。您想要处理此连接的线程也可能被阻止读取,因此您需要一些机制来唤醒它。

      第二个问题至少分开了一些问题(读/发与处理)。


明智地,您的设计应该依赖于

  • 客户数量
  • I / O加载
  • 非I / O处理量(或IO:CPU比率,或......)

答案 1 :(得分:1)

我的服务器做的第一件事是创建一种线程池;它创建了5个线程,所有线程都被recvfrom()函数自动阻塞,虽然看起来,在我将多个线程连接到服务器的大多数时候,多个线程正在响应,之后导致服务器变为完全阻止而不能进一步操作

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

我认为要采用的方法是在主线程中使用select,并使用并发缓冲区来管理线程将执行的操作。 在此解决方案中,每个客户端可以有一个线程,或者每个文件有一个线程,假设您保留客户端必要的信息以确保您发送正确的文件部分。

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