服务器可以在一个线程中处理多个套接字吗?

时间:2013-09-16 20:24:08

标签: sockets

我正在编写一个需要模拟虚拟机之间的多个连接的测试程序,看起来最好的方法是使用Unix域套接字,原因各种各样。我是否使用SOCK_STREAM或SOCK_DGRAM并不重要,但似乎SOCK_STREAM对我的使用更容易/更简单。

我的问题似乎与典型情况有点相反。我想让一个客户端通过4个不同的套接字与服务器通信。 (我可以有4个客户端,每个都有一个套接字,但这种区别无关紧要。)现在,我正在模拟的东西没有多个线程,并且只要通过其中一个“套接字”接收到数据包就会收到中断”。有没有一些简单的方法来使用Unix套接字来模拟它?

我认为我必须先为所有4个套接字执行socket()bind()listen(),然后为所有4个套接字执行accept(),并执行{每个{1}}使其无阻塞,以便我可以循环方式检查每个数据fcntl( fd, F_SETFF, FNDELAY )的数据。有没有办法让它成为中断驱动或事件驱动的,这样我的主循环只检查套接字中的数据,如果那里有数据的话?或者像这样对他们进行轮询更好吗?

1 个答案:

答案 0 :(得分:4)

是。处理多个连接几乎与“服务器”同义,并且它们通常是单线程的 - 但请不要这样:

  

以循环方式检查每个数据的read()

正如你所提到的那样,这需要非阻塞套接字以及某种延迟来阻止你的“循环”成为一个系统杀死繁忙的循环。

一个主要问题是延迟的粒度。你不能把它做得太小,否则当没有任何事情发生时,循环仍会占用太多的CPU时间。但是当 发生什么事情,以及某些事情是多个连接上同时传入的数据时呢?现在,你的延迟会导致积雪的积压导致拒绝连接等等。

这是不可行的,并且没有人以这种方式编写服务器,但我相信如果他们不知道用于解决问题的库函数,任何人都会认真考虑。请注意,网络是一个特定于平台的问题,因此它们实际上并不是C标准的一部分(它根本不涉及套接字)。

功能为select()poll()epoll();最后一个是特定于Linux的,另外两个是POSIX。基本思想是呼叫阻塞,等待任意数量的活动连接中的一个或多个准备好读取或写入。等待套接字准备好只能有意义地写入NON_BLOCK套接字。但是,您不必使用NON_BLOCK,而是select()调用块。在各个套接字上使用NON_BLOCK会使实现更复杂,但会增加单线程服务器的性能 - 这是异步服务器(例如 nginx )背后的理念,与更传统的线程同步模型形成对比的范例。

但是,我建议您最初不要使用NON_BLOCK,因为增加了复杂性。当/如果它最终被要求,你会知道。你仍然不需要线程。

关于如何特别使用select(),有许多很多很多示例和教程。