2012-02-24 95 views
2

第一件事是,我是一個很長時間的潛伏者,但第一次用戶,我想感謝您創建網站!專用協議的長期多線程客戶端(Python,select,epoll)

我處於需要實現專有協議的客戶端部分的情況。該協議使用TCP/IP的下方和消息流可以被總結如下:

  1. 客戶機連接到服務器
  2. 客戶端表示在一個特定類型的數據中的感興趣
  3. 如果服務器具有任何這樣的數據,它它發送到客戶端
  4. 客戶確認接收到服務器
  5. 客戶現在需要告訴它仍有意在同類型
  6. 服務器的數據的服務器將數據發送到客戶端它是在
  7. 客戶未來需要的應用程序級的保活請求從時間發送到服務器的時間(如每分鐘左右)
  8. 從服務器的一些消息需要客戶端發送回覆回服務器
  9. 客戶端斷開

所有這一切是在一個TCP會話,這將是一個長期的活的,有點像我的WebSocket想象中發生。

另一件事是,所述客戶端將被部署在多線程服務器上,並且應該允許從多個線程的併發訪問,這意味着單個線程應該能夠從到「訂閱」到某一類型的消息服務器也應該能夠發送消息給它。

我非常瞭解GIL,因此我猜這並沒有太多的評論,我只寫了一個客戶端,我無法改變任何其他的架構。

因此,事情是我從來沒有深入HTTP層次,我很幸運,總是使用一些已經存在的庫,另一方面,我沒有做過那麼多的網絡編程,那將是我第一次成爲這樣的人。

我希望它能成爲我學習更多關於select,epoll,libev或gevent等異步庫/工具/工具包的機會。

麻煩的是,網絡上的大部分資源都與編寫服務器有關,我甚至不確定是否要在多線程上部署客戶端並不意味着它們都不會多做。所有服務器的人顯然都是單線程的,但不清楚是不是因爲多線程不需要,或者是因爲像epoll這樣的東西並不真的喜歡使用它們的多線程。

服務器清楚地對待所有客戶端,就像它們是單線程單元一樣,所以我想我需要序列化訪問客戶端。我無法得到的是如何確保服務器響應匹配線程,反之亦然。如果一個線程收到一條消息,但另一個線程需要確認它在收到消息之前收到的消息,那麼我怎樣才能確保消息不會混淆?

你怎麼看待這一切?在這種情況下,異步庫是不錯的選擇嗎?你能想到我可以看看的任何代碼示例嗎?我使用的是Python,但我認爲這個問題足夠通用,我可以使用C,C++或Java來獲得靈感。

很多,非常感謝!

回答

0

每個線程(每個客戶端)是否可以打開自己的套接字?在這種情況下,這完全是一個非問題:只有該線程中的客戶端在該套接字上具有句柄,因此它會自動從服務器獲取正確的數據。對於服務器,來自客戶端的所有這些連接將看起來像完全獨立的客戶端連接(這正是它們的原理)。

如果其中一個要求是限制網絡連接的總數,那麼您可以構建一個特殊線程來維護到服務器的連接,並且在本地接收來自各個線程的通信請求/但是使用獨立套接字每個線程一個)可能要簡單得多。

您是否絕對必須使用應用程序級保持活動?因爲TCP可以自動爲你做到這一點。如果沒有及時收到keepalive,那麼套接字會關閉,從而通知對方連接已超時。如果在你的情況下可能,請考慮將它作爲一個選項。最後,如果您不必執行應用程序級別的keepalive,那麼您可以利用多線程編程的一個好方面:將每個線程開發爲好像它是唯一的一個線程,然後您不用根本不需要擔心任何異步。例如,您可以編寫客戶端發送請求,然後阻塞 - 等待響應,計算併發送結果或檢查服務器是否有更多數據到達。來自服務器的數據將累積在您的TCP接收窗口中。這也可以作爲流量控制的一種手段:如果客戶端變得太慢並且接收窗口已滿,則服務器無法再發送。這可能會阻塞服務器,所以您需要查看服務器是否可以處理這種情況。