2017-10-23 8 views
0

私は、あるコンピュータから別のコンピュータにデータを転送するPythonソケットでTCPを使用しています。しかし、recvコマンドではサーバ側でそれよりも多くのコマンドを読み取るため、問題が見つかりませんでした。TCPソケットが順番に読み取る

client.py

while rval: 
    image_string = frame.tostring() 
    sock.sendall(image_string) 
    rval, frame = vc.read() 

server.py

while True: 
    image_string = "" 
    while len(image_string) < message_size: 
     data = conn.recv(message_size) 
     image_string += data 

受け取ったときに、私は印刷するときに、メッセージの長さは、それは、しかしながら、sendall921600 (message_size)送信されます到着したメッセージの長さ、長さが間違っていることがあります。

921600 
921600 
921923 # wrong 
922601 # wrong 
921682 # wrong 
921600 
921600 
921780 # wrong 

ご覧のとおり、間違った到着にはパターンがありません。私はTCPを使うので、より一貫性があると思いましたが、バッファが混ざっていて、次のメッセージの一部を何とか受け取っているように見えます。 ここで問題は何ですか?

コードの関連部分だけを追加しようとしましたが、必要に応じて追加することができますが、コードはlocalhostで正常に動作しますが、2台のコンピュータでエラーが発生するため、

EDIT1:私はこのquestionを少し検査、それはすべてのクライアントにコマンドを送信することを言及しているサーバーで単一のrecvで受け取ったことがないかもしれませんが、私は実際にこれを適用する方法を理解できませんでした。

答えて

1

TCPはストリームプロトコルです。送信するチャンクのサイズと受け取るデータのチャンクの間には絶対的な接続はありません。既知のサイズのデータ​​を受信したい場合、大量のデータのみを要求することはあなた次第です。現在はデータの全長を要求していますが、これはおそらくそうした場合を除いてあまりにも多くのデータを読み込もうとします最初の.recv()コールによってデータ全体のイベントが取得されます。基本的には、残りのデータ量が減少していることを反映するために、data = conn.recv(message_size - len(image_string))のようなものを実行する必要があります。

+0

あなたが言うように、私はそれも必要ない、 'recv(message_size)'で十分でしょうか? – Rockybilly

+0

1つの 'recv()'が要求されたバイトをすべて読み取るという保証はありません。これまでにネットワーク経由で受け取ったものがすべてであれば、それは少なくなります。 – jasonharper

+0

ストリームベースの場合は、バッファがメッセージで満たされるまで読み込まないでください。そして、私がこのテーマについてもっと読むことができるリソースがあると、Pythonのドキュメントはこのように短くなります。 – Rockybilly

1

バイトを生ストリームとしてTCPを考えます。ストリーム内のどこを追跡し、正しく解釈するのはあなたの責任です。あなたが読んだものをバッファリングし、現在必要なものだけを抽出します。ここで

は説明する(未テスト)クラスです:

class Buffer: 
    def __init__(self,socket): 
     self.socket = socket 
     self.buffer = b'' 
    def recv_exactly(self,count): 
     # Could return less if socket closes early... 
     while len(self.buffer) < count: 
      data = self.socket.recv(4096) 
      if not data: break 
      self.buffer += data 
     ret,self.buffer = self.buffer[:count],self.buffer[count:] 
     return ret 

recvは常にデータとバッファ内のキュー、それを同じ量を要求します。 recv_exactlyは、要求されたバイト数だけを返し、余分なものはバッファに残します。

関連する問題