在工作中,我的任务是将TCP服务器作为Modbus从设备的一部分来实现。我已经在堆栈交换和一般的互联网上做了很多阅读(包括优秀的http://beej.us/guide/bgnet/),但我正在努力解决设计问题。总之,我的设备只能接受2个连接,并且在每个连接上都是传入的modbus请求,我必须在主控制器循环中处理这些请求,然后回复成功或失败状态。我对如何实现这个有以下想法。
拥有一个创建,绑定,侦听和接受连接的侦听器线程,然后生成一个新的pthread来监听连接以获取传入数据并在空闲超时期限后关闭连接。如果活动线程数目前为2,则立即关闭新连接以确保只允许2个。
不要从侦听器线程生成新线程,而是使用select()来检测传入的连接请求以及活动连接上的传入modbus连接(类似于Beejs指南中的方法)。
< / LI>我一直在使用C ++,但我对Linux开发还不熟悉。我真的很欢迎任何关于上述哪种方法最好的建议(如果有的话)以及我对Linux的经验不足意味着他们中的任何一个都是非常糟糕的想法。我希望避免fork()并坚持使用pthreads,因为传入的modbus请求将被排队并定期从主控制器循环读取。提前感谢任何建议。
答案 0 :(得分:3)
第三种方法不起作用,你只能绑定一次本地地址。
我可能会使用你的第二种选择,除非你需要做很多处理,在这种情况下,第一种替代方案的组合可能是有用的。
我想到的两个第一个替代方案的组合是让主线程(程序启动时总是有的)创建两个工作线程,然后进行阻塞accept
调用等待一个新的连接。当新连接到达时,告诉其中一个线程开始处理新连接并返回阻止accept
。当第二个连接被接受时,您告诉另一个线程在该连接上工作。如果两个连接都已打开,则在关闭一个连接之前不要接受,或等待新连接但立即关闭它们。
答案 1 :(得分:2)
由于您只处理2个连接,因此每个连接的线程非常适合此类应用程序。如果需要扩展到数千个连接,使用非阻塞或异步I / O的面向对象方法会更好。 2个监听线程有意义,你不需要关闭接受fd。连接完成后再回来接受它。事实上,一个变化是阻止三个线程做接受。如果其中两个线程正在主动处理连接,则第三个线程将重置新创建的连接(或返回忙响应,适用于您的设备)。
要让所有三个线程都阻塞接受,你需要让主线程在三个线程启动之前创建并绑定你的套接字以进行接受/处理。
man page for pthreads on Linux表示接受是线程安全的。 (线程安全函数下的部分列出了非线程安全的函数,如图所示。)
答案 2 :(得分:2)
你提出的所有设计选项都不是面向对象的,而且他们更倾向于C而不是C ++。如果你的工作允许你使用boost,那么Boost.Asio库非常适合制作简单(和复杂)的套接字服务器。您几乎可以使用他们的任何示例,并将其扩展为仅允许2个活动连接,一旦打开就关闭所有其他连接。
在我的脑海中,可以通过在连接类中保留静态计数器(构造函数中的inc,析构函数中的dec)来修改它们的简单HTTP服务器,并在创建新的计数器时检查计算并决定是否关闭连接。连接类也可以获得一个boost :: asio :: deadline_timer来跟踪超时。
这最类似于你的第一个设计选择,boost可以在1个线程中执行此操作,而在后台执行与select()
类似的操作(通常为epoll()
)。但这是&#34; C ++方式&#34;,在我看来,使用select()
和原始pthread
是C方式。