簡體   English   中英

在python和Qt之間進行TCP連接的正確方法?

[英]Right way to do TCP connection between python and Qt?

我想通過TCP連接兩個程序。 我的主程序是用Qt編寫的,需要與另一個用Python編寫的程序對話。 我考慮使用TCP套接字和Google的protobuf交換消息。 在Qt中,我使用一個QTcpSocket,它會在其readyRead-Signal觸發后立即接受連接並從流中讀取。 在python中,我還使用tcp-socket並發送消息。

只要沒有一方被殺死,這將非常有效。 目前,python端正在向C ++端發送消息。 socket.send(str(id)+"\\ņ") )在每次發送后,我檢查是否有異常(對等連接重置,管道斷開等),以查看是否收到了消息。 如果我殺死了C ++程序,則從python客戶端發送的下一條消息不會觸發任何異常,但顯然不會收到。 下一條消息觸發異常,但最后一條消息丟失。

經過一些試驗,我發現在每條消息后發送一個空消息( socket.send("\\n") )可以解決問題。 我現在做的

try:
  s.send(str(id)+"\n");
  s.send("\n")
  sleep(0.5)
except socket.error,v: 
   print "FAILed to send",id,v[0],v[1]

並在C ++-Peer被殺死后立即收到異常(調用s.send(str(id)+"\\n\\n")卻無濟於事)。

最后,我的問題是:這是檢查是否收到我的消息的可靠方法嗎? 我不想切換到UDP,因為我不想為每個消息實現自己的ACK消息。

這是我第一次將套接字與python和C ++一起使用,無法真正解釋為什么我的方法行得通,因此使用它有點不舒服。

有人可以告訴我更多嗎? 我想,蟒插座預計用於第一的ACK send(int(id)+"\\n")發送后send("\\n") ,然后意識到管道損壞。 這個對嗎?

當TCP連接被遠程對等方斷開時,您的TCP套接字將變為可讀取狀態,然后當您嘗試從中讀取recv()時,recv()將返回0。

當然,如果您的發送程序僅調用send()(Python程序的方式),則它不會注意到套接字的recv側發生了什么,最終您遇到了所描述的問題。

另一方面,您也不想盲目調用recv(),因為如果調用recv()並且遠程對等方未發送任何數據,則recv()將阻止等待數據,除非遠程對等方實際上,如果發送一些,就會陷入僵局。

處理該問題的最簡單方法是使用select()復用您的I / O,以便您的Python腳本可以知道何時調用send()和/或recv()。 像這樣:

import socket
import select

[...]
while 1:
   socketsToReadFrom = [s]
   if (you_still_have_more_data_to_send):
       socketsToWriteTo = [s]
   else:
       socketsToWriteTo = None

   # This select() call will block until there's something to do
   socketsReadForRead, socketsReadyForWrite, junk = select.select(socketsToReadFrom, socketsToWriteTo, None)

   if (s in socketsToReadFrom):
      readBytes = s.recv(1024)
      if (len(readBytes) > 0): 
         print "Read %i bytes from remote peer!" % readBytes
      else:
         print "Remote peer closed the TCP Connection!!"
         break

   if ((socketsToWriteTo != None) and (s in socketsToWriteTo)):
      s.send(some_more_data)

至於驗證是否收到您的消息,這有點棘手,因為TCP(和網絡堆棧)進行了大量的流水線/緩沖。 特別是,從send()成功返回僅表明您的數據已移交給本地TCP堆棧的傳出數據緩沖區。 這並不意味着數據已經到達遠程對等方。 如果您確實希望遠程對等方已經處理了數據,則必須讓遠程對等方發回某種確認。 請注意,在TCP下,盡管沒有網絡或硬件故障(或遠程對等方關閉TCP連接),但通常不需要復雜的級別,因此,您可以確定TCP堆棧最終將在此獲取數據。 例如,如果數據包丟失,TCP堆棧將自動重新發送它。 僅當網絡連接長時間(例如幾分鍾)停止工作時,才會發生數據丟失,此時TCP堆棧將放棄並關閉TCP連接。

暫無
暫無

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

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