我正在编写一个需要模拟虚拟机之间多个连接的测试程序,出于各种原因,似乎最好的方法是使用 Unix 域套接字。我是使用 SOCK_STREAM 还是 SOCK_DGRAM 并不重要,但看起来 SOCK_STREAM 对我来说更容易/更简单。
我的问题似乎与典型场景有点倒退。我想让一个客户端通过 4 个不同的套接字与服务器通信。(我可以有 4 个客户端,每个客户端有一个套接字,但这种区别应该无关紧要。)现在,我正在模拟的东西没有多个线程,并且每当通过“套接字”之一接收到数据包时都会得到中断”。有没有一些简单的方法可以用 Unix 套接字模拟这个?
我认为我必须做的socket(),bind()和listen()所有4个插槽第一,然后做一个accept()对所有4个,并做fcntl( fd, F_SETFF, FNDELAY )了每个人,使他们非阻塞,这样我可以检查每一个数据read()在一个循环的方式. 有什么方法可以使它成为中断驱动或事件驱动,以便我的主循环仅在套接字中有数据时才检查套接字中的数据吗?或者像这样对他们进行投票是否更好?
是的。处理多个连接几乎是“服务器”的同义词,它们通常是单线程的——但请不要这样:
以循环方式使用 read() 检查每个数据
正如您所提到的,这将需要非阻塞套接字和某种延迟,以防止您的“循环”成为系统终止繁忙循环。
一个主要问题是延迟的粒度。你不能让它太小,否则当什么都没有发生时循环仍然会占用太多的 CPU 时间。可是你知道当事情被发生的事情,这东西是数据上的多个连接同时进来的?现在,您的延迟会产生滚雪球般的积压,导致连接被拒绝等。
这是不可行的,没有人以这种方式编写服务器,尽管我相信如果他们不知道旨在解决问题的库函数,任何人都会认真考虑。请注意,网络是特定于平台的问题,因此这些实际上不是 C 标准的一部分(根本不处理套接字)。
函数是select(), poll(), 和epoll(); 最后一个是特定于 linux 的,另外两个是 POSIX。基本思想是调用阻塞,等待任意数量的活动连接中的一个或多个准备好读取或写入。等待套接字准备好写入仅有意义地适用于 NON_BLOCK 套接字。但是,您不必使用 NON_BLOCK,并且无论如何select()调用都会阻塞。在单个套接字上使用 NON_BLOCK 会使实现更加复杂,但会增加单线程服务器的性能潜力——这是异步服务器(例如nginx)背后的想法,一种与更传统的线程同步模型形成对比的范例。
但是,由于增加了复杂性,我建议您最初不要使用 NON_BLOCK。何时/如果它最终被调用,你就会知道。您仍然不需要线程。
有很多很多关于如何使用的示例和教程select()。