2017-10-15 71 views
0

是否可以通過多個線程與單個端口上的TCP套接字服務器進行通信,共享一個公用套接字或使用獨立套接字,而無需鎖定機制或其他跨線程通信技術?多線程套接字客戶端衝突

我的具體問題:

我在python socket編程初學者,試圖寫一個聯網的家庭自動化設備(GlobalCache GC100)

接口庫我需要在兩個經常聽取用於通過TCP從該硬件獲取傳感器狀態改變事件,並且能夠在用戶啓動的時間發送set_state命令(跳閘繼電器),而沒有顯着的延遲。

我有一個while True:循環,執行socket.recv()拾取狀態更改事件。大多數情況下會超時(socket.settimeout(10))並繼續進行下一次循環迭代,直到設備推送狀態更改數據。

現在最重要的是我需要用戶能夠發送set_state命令,我不希望用戶需要等到socket.recv()超時並注入recv()之間的通信,循環迭代。所以我選擇使用它自己的套接字將tcp監聽循環分成單獨的線程(但指向同一主機端口&)。

問題是,set_state線程中的套接字似乎殺死了偵聽線程中的套接字,反之亦然。看來只有最近創建/連接的套接字實際上是功能性的。

我想要做一些套接字編程不可能的事情,或者這可能只是我的設備上的套接字服務器實現(GC-100)的限制嗎?

到目前爲止我唯一可以看到的解決方案是,在一個線程中保持所有套接字通信,使用通用套接字,實現通信隊列,並將超時持續時間保持爲tcp-listening部分的非常小的值,所以set_state命令必須在隊列中等待最少的時間。但這似乎並不理想,有些脆弱。

編輯:

它是套接字對(由客戶端IP 地址,客戶端端口號,服務器IP地址的四元組,和服務器端口 號碼),指定所述兩個唯一標識互聯網中每個 TCP連接的端點。 (TCP-IP詳解卷1,W 理查德·史蒂文斯)

我想也許我需要強制通過在不同的線程的多個插座使用的源端口的差異。我嘗試了socket.bind(hostname, source_port),但不斷收到地址已被使用的錯誤,對於主機名爲&的所有組合似乎都是合理的。

+0

單個TCP套接字完全能夠同時發送/接收數據。 – bnaecker

+0

@bnaecker我意識到我的描述並不是特別擅長說明具體問題,所以我編輯了它。我的問題與通過一個或多個套接字同時在不同線程上與一個主機和端口進行通信有關。 – davegravy

+0

用戶如何將命令發送到設備?如果它通過文本/命令行界面之類的東西,則可以使用IO多路複用來處理單個套接字上的所有內容。查看'select'或'selectors'模塊,您可以無限期地等待,直到用戶輸入命令或設備發送狀態更新。 – bnaecker

回答

0

雖然沒有在他們的API文檔中提到,但我相信這是GC-100服務器實現的限制。有很多關於如何實現可以支持來自多個主機的同時連接的tcp服務器的例子。然而,我配置了兩臺不同的主機連接到設備,而設備一次只允許連接一臺主機。

因此,對我來說似乎唯一的解決方案是使用一個單一的套接字,並複用所有的閱讀和寫作。

http://wiki.linuxmce.org/index.php/GlobalCache_GC-100#Implementation_details

的GC100軟件體系結構使用兩個線程,用於接收(EventThread)與 關於繼電器,IR發射器和傳感器的GC100,一個用於 發送消息(SocketThread)和一個進行通信。 原因是gc100協議並不完全是 請求 - 回覆協議,即使它看起來像這樣。 gc100 可以在傳感器跳閘時啓動傳輸,足以中斷請求 - 回覆範例。該程序旨在將 通信視爲異步。消息被髮送到設備而沒有 期待回覆,並且回覆將被視爲獨立事件 和狀態更改報告,而不會將請求鏈接到 程序邏輯中的回覆(初始化階段除外)。