在Linux上编写multithreadingTCP服务器

在工作中,我负责将TCP服务器作为Modbus从站设备的一部分来实现。 我在堆栈交换和一般的互联网(包括优秀的http://beej.us/guide/bgnet/ )上都做了大量的阅读,但是我正在为devise问题而苦苦挣扎。 总之,我的设备只能接受2个连接,每个连接都会接收到我在主控制器环路中必须处理的modbus请求,然后回复成功或失败状态。 我有如何实现这一点的以下想法。

  1. 有一个侦听器线程创build,绑定,侦听和接受连接,然后生成一个新的pthread来监听传入数据的连接,并在空闲超时期限后closures连接。 如果当前活动线程的数量是2,则立即closures新的连接以确保只允许2个连接。

  2. 不要从侦听器线程产生新线程,而是使用select()来检测传入的连接请求,以及在活动连接上传入的modbus连接(类似于Beejs指南中的方法)。

  3. 创build两个监听器线程,每个监听器线程创build一个可以阻塞accept()调用的套接字(相同的IP和端口号),然后closures套接字fd并处理连接。 在这里,我(可能天真地)认为这将只允许最多2个连接,我可以使用阻塞读取处理。

我一直在使用C ++很长一段时间,但对于Linux开发来说,我还是比较新的。 对于上述哪种方法最好(如果有的话),以及如果我对Linux的经验不足意味着其中任何一个都是非常糟糕的想法,我都非常欢迎。 我渴望避免fork()并坚持pthreads,因为传入的modbus请求将被排队并定期从主控制器循环读取。 预先感谢您的任何build议。

第三个选择将不起作用,你只能绑定到本地地址一次。

我可能会使用你的第二个选择,除非你需要做很多的处理,在这种情况下,第一个替代品的组合可能是有用的。

我想到的两个第一个替代方案的组合是让主线程(程序启动时总是有的)创建两个工作线程,然后进行阻塞accept调用以等待新的连接。 当一个新的连接到达时,告诉其中一个线程开始处理新的连接,然后回到阻止accept 。 当第二个连接被接受时,告诉另一个线程在该连接上工作。 如果两个连接都已打开,请等待一个连接关闭,或者等待新连接,但立即关闭。

你提出的所有设计选项都不是非常面向对象的,它们都比C ++更适合C语言。 如果您的工作允许您使用boost,那么Boost.Asio库对于制作简单(和复杂的)套接字服务器来说是非常棒的。 你几乎可以拿任何一个例子,并且简单地扩展它,只允许2个活动的连接,打开后立即关闭所有其他的连接。

在我的头顶,他们的简单的HTTP服务器可以通过在连接类中保留一个静态计数器(在构造函数中的dec,在析构函数中的dec)进行修改,当创建一个新的时,检查计数并决定是否关闭连接。 连接类也可以获得boost :: asio :: deadline_timer来跟踪超时。

这将最接近你的第一个设计选择,boost可以在1线程中做到这一点,在后台做类似于select() (通常epoll() )。 但是这是“C ++方法”,在我看来,使用select()和raw pthread s是C方法。

由于您只处理2个连接,每个连接的线程对于这种应用程序来说是完美的。 如果您需要扩展到数千个连接,使用非阻塞或异步I / O的面向对象的方法会更好。 2个监听线程是有意义的,你不需要关闭接受fd。 连接完成后再回来接受。 实际上,一个变种是有三个线程被阻止接受。 如果其中两个线程正在主动处理连接,则第三个将重置新创建的连接(或返回忙碌响应,无论适用于您的设备)。

为了让所有三个线程都被阻塞,你需要让主线程在三个线程启动之前创建并绑定你的套接字来完成它们的接受/处理处理。

Linux上的pthreads手册页表明accept是线程安全的。 (线程安全函数下的部分列出了不是线程安全的函数,请参阅图)。