6

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

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

我相信我必须首先对所有 4 个套接字执行socket()bind()listen(),然后对所有 4 个套接字执行一次,然后对每个套接字accept()执行fcntl( fd, F_SETFF, FNDELAY )一次以使它们成为非阻塞,这样我就可以以read()循环方式检查每个套接字的数据. 有没有办法让它成为中断驱动或事件驱动的,这样我的主循环只检查套接字中的数据是否有数据?还是像这样轮询他们更好?

4

1 回答 1

6

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

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

正如您所提到的,这将需要非阻塞套接字和某种延迟,以防止您的“循环”成为系统杀死繁忙循环。

一个主要问题是延迟的粒度。你不能让它太小,否则当什么都没有发生时,循环仍然会占用太多的 CPU 时间。但是,当某事发生时,并且某事是在多个连接上同时传入的数据时呢现在,您的延迟可能会产生滚雪球般的积压,导致连接被拒绝等。

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

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

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

有很多很多很多关于如何使用select()的示例和教程。

于 2013-09-16T22:40:46.153 回答