簡體   English   中英

在Linux上編寫多線程TCP服務器

[英]Writing multithreaded TCP server on Linux

在工作中,我的任務是將TCP服務器作為Modbus從設備的一部分來實現。 我已經在堆棧交換和一般的互聯網上做了很多閱讀(包括優秀的http://beej.us/guide/bgnet/ ),但我正在努力解決設計問題。 總之,我的設備只能接受2個連接,並且在每個連接上都是傳入的modbus請求,我必須在主控制器循環中處理這些請求,然后回復成功或失敗狀態。 我有如何實現這一點的以下想法。

  1. 有一個創建,綁定,偵聽和接受連接的偵聽器線程,然后生成一個新的pthread來監聽連接以獲取傳入數據並在空閑超時期限后關閉連接。 如果活動線程的數量當前為2,則立即關閉新連接以確保僅允許2個。

  2. 不要從偵聽器線程生成新線程,而是使用select()來檢測傳入的連接請求以及活動連接上的傳入modbus連接(類似於Beejs指南中的方法)。

  3. 創建2個偵聽器線程,每個線程創建一個套接字(相同的IP和端口號),可以阻止accept()調用,然后關閉套接字fd並處理連接。 在這里,我(或許天真)假設這將只允許最多2個連接,我可以使用阻塞讀取來處理。

我一直在使用C ++,但我對Linux開發還不熟悉。 我真的很歡迎任何關於上述哪種方法最好的建議(如果有的話)以及我對Linux的經驗不足意味着他們中的任何一個都是非常糟糕的想法。 我希望避免fork()並堅持使用pthreads,因為傳入的modbus請求將被排隊並定期從主控制器循環讀取。 提前感謝任何建議。

第三種方法不起作用,你只能綁定到本地地址一次。

我可能會使用您的第二種替代方案,除非您需要進行大量處理,在這種情況下,第一種替代方案的組合可能會有用。

我想到的兩個第一個替代方案的組合是讓主線程(程序啟動時總是有的)創建兩個工作線程,然后進行阻塞accept調用以等待新連接。 當新連接到達時,告訴其中一個線程開始處理新連接並返回阻止accept 當第二個連接被接受時,您告訴另一個線程在該連接上工作。 如果兩個連接都已打開,則在關閉一個連接之前不要接受,或等待新連接但立即關閉它們。

由於您只處理2個連接,因此每個連接的線程非常適合此類應用程序。 如果需要擴展到數千個連接,使用非阻塞或異步I / O的面向對象方法會更好。 2個監聽線程有意義,你不需要關閉接受fd。 連接完成后再回來接受它。 事實上,一個變化是阻止三個線程做接受。 如果其中兩個線程正在主動處理連接,則第三個線程將重置新創建的連接(或返回忙響應,適用於您的設備)。

要讓所有三個線程都阻塞接受,您需要讓主線程在三個線程啟動之前創建並綁定套接字以進行接受/處理。

Linux上pthreads手冊頁表明accept是線程安全的。 (線程安全函數下的部分列出了非線程安全的函數,如圖所示。)

你提出的所有設計選項都不是面向對象的,而且它們都更傾向於C而不是C ++。 如果你的工作允許你使用boost,那么Boost.Asio庫非常適合制作簡單(和復雜)的套接字服務器。 您可以接受幾乎任何示例,並將其擴展為僅允許2個活動連接,一打開就關閉所有其他連接。

通過在連接類(構造函數中的inc,析構函數中的dec)中保留靜態計數器,可以修改它們的簡單HTTP服務器來執行此操作,並在創建新計數器時檢查計數並確定是否關閉連接。 連接類也可以獲得boost :: asio :: deadline_timer來跟蹤超時。

這最類似於你的第一個設計選擇,boost可以在1個線程中執行此操作,而在后台執行類似於select() (通常是epoll() )。 但這是“C ++方式”,在我看來,使用select()和原始pthread是C方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM