2016-10-08 33 views
1

私はPythonサーバーからPythonクライアントにソケット経由でマウス座標を送信します。マウスの動きのイベントがサーバー上で捕捉されるたびに、マウス座標が送信されます。これはかなり頻繁に(1秒間に12回程度)意味します。Pythonソケットrecv()は、あまりにも速すぎるとすべてのメッセージを取得しません。

問題は、別のホストでpythonサーバーとpythonクライアントを使用するときです。その後、メッセージの一部のみがクライアントに配信されます。例: 3つの最初のメッセージが配信され、4つのメッセージが配信されず、4つのメッセージが配信されます。

サーバとクライアントが同じホスト(ローカルホスト)にある場合はすべて問題ありません。

サーバーとクライアントが異なるホスト上にある場合はすべて問題ありませんが、Pythonクライアントではなく、標準のWindows Telnetクライアントを使用してサーバーからメッセージを読み取ります。

私は、送信される各メッセージの間にtime.sleep(0.4)ブレークを使用すると、すべてのメッセージが配信されることに気付きました。問題はそのような遅れではなくリアルタイムでその情報を必要とすることです。ソケットを使ってPythonでそれを実現することは可能ですか? Pythonクライアントコードの下

私が使用している:

import pickle 
import socket 
import sys 


host = '192.168.1.222' 
port = 8888 
try: 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
except socket.error, msg: 
    print "Faile. Error:" + str(msg[0]), "Error message : " + msg[1] 
    sys.exit() 

mySocket = socket.socket() 
mySocket.connect((host,port)) 

while 1: 
    data = mySocket.recv(1024) 
    if not data: break 
    load_data = pickle.loads(data) 

    print 'parametr x: ' + str(load_data[0]) 
    print 'parametr y : ' + str(load_data[1]) 

mySocket.close() 

答えて

3

あなたは、受信者が読んでいない場合であっても、すべてのメッセージを失わない(UDPに反して)信頼できるプロトコルであるTCP(SOCK_STREAM)を使用していますデータは十分に速い。代わりに、TCPは送信速度を低下させます。
これは、問題がアプリケーションコードのどこかにあることを意味します。

送信者に問題があります。つまり、socket.sendを使用し、送信するすべてのバイトが実際に送信されたかどうかを確認しないでください。しかし、このチェックは、クライアントがデータを十分に速く読み取らない場合に起こりうる、OSのソケットバッファがいっぱいである場合にのみ、socket.sendがデータの一部を送信する可能性があるので、行わなければならない。

もう一つの可能​​性は、あなたのsocket.recvコールがあなたのpickle.loads必要以上のデータを受信し、データの残りは(あまりにも多くのデータが提供されている場合pickle.loadsが例外をスローするかどうかわからない)に廃棄されることをということです。 TCPはメッセージではなくストリームプロトコルであるため、socket.recvは複数のピクルされたオブジェクトを含むバッファを返しますが、最初のものだけを読むことになります。これがネットワーク上で起こる可能性は、デフォルトでは、接続をより良く(すなわちオーバーヘッドの少ない)ために複数のsendバッファを1つのTCPパケットに連結しようとするためです。そしてチャンスは高いので、同じrecvコールの中で受け取られるでしょう。 sleep(0.4)を送信側に置くことで、このTCPの最適化を効果的に無効にすることができます。詳しくは、NAGLE algorithmを参照してください。

したがって、あなたが望むものを実装するための正しい方法は次のようになります。

  • すなわちsocket.sendのリターンをチェックし、すべてのデータがサーバーに配信されていることを確認します。
  • 受信したすべてのメッセージを解凍してください。これを行うには、メッセージ境界がどこにあるかを知るために、TCPストリームの上にメッセージレイヤーを追加する必要があります。
+0

あなたは正しいです!私はただちにチェックをしました。そして、私は、配信されたメッセージの一部だけを読むことが判明しました。あなたが述べたように、いくつかのメッセージは連結され、私はそれらを正しく読まない。 'pickle.loads'はどんな例外も投げなかったので、私を騙しました。今私はそれらをすべて読む方法を理解する必要があります。 – michal2616

+0

OPはすべてのデータが確実に送信されるように['socket.sendall()'](https://docs.python.org/2/library/socket.html#socket.socket.sendall)を試すことができます。 – mhawke

関連する問題