2016-10-20 7 views
2

私は、自分自身の他のコピーにパケットを送るプログラムでうんざりしていますが、recvfromは私が完全に理解できない方法で動作しています。プログラムの各インスタンスは、別のポート(dictMapディクショナリにすでに格納されている他のインスタンスのポート番号の知識を持つ)に設定されます。私がこのプログラムのいくつかのインスタンス(例えば8)を起動した後、それらはすべて互いに1秒間に3回(MINI_UPDATE_INTERVAL)相互にpingする必要があるという考えがあります。ソケットへの複数の接続時のrecvfrom()の動作

しかし、全体の束が実行されている間にインスタンスの1つを閉じると、プログラムはすべて「醜い切断が検出されました。切断されたインスタンスが1回だけ切断されたとしても、複数回実行されます。これの背後にある理由は何ですか?私のコードの一部は以下の通りです:

PORT = int(args.port) 
socket.setdefaulttimeout(1) 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,0)#make udp socket and use it to connect 
s.bind(("",PORT)) 
s.setblocking(False) 


#timing considerations 
STARTTIME = time.time() 
prevsent = STARTTIME 


print "Node started..." 
while True: 

    readable, writable, err = select.select([s],[s],[s]) #using select to poll our socket to see if it is readable 

    for sock in writable:#if s is writable (it should be), there are packets in the send queue AND one of the next two conditions is met: 
     if forwardQueue: 
      msgArr = forwardQueue.pop(0) 
      sock.sendto(msgArr[MSG],("127.0.0.1",int(msgArr[DESTPORT]))) 


    for sock in readable: #if there's something to be read... 
     try: 
      recvMsg, addr = sock.recvfrom(2048) 
     except: 
      print "ugly disconnect detected" + str(addr[1]) + recvMsg 
      break 



    for sock in err: 
     print "ERROR" 



    if time.time() - MINI_UPDATE_INTERVAL > prevsent: #once a second 
     # print time.time() - STARTTIME 

     for key,value in dictMap.iteritems(): 
      forwardQueue.append([('PING'+ '|'+idName+'|'+str(time.time())),value]) 

EDIT:問題は、Windows上でのみ発生するようです(WSAECONNRESETは常に切断後にポップアップ続けています)。私のコードは最終的にLinux向けになっているので大したことではないと思います。

+0

udpソケットで切断メッセージがどこから来たのかわからない。接続されていないので、切断されていない可能性があります。たぶんあなたは例外ではないと思っていますか?なぜあなたは実際に例外をつかんでその詳細を印刷しないのですか? – xaxxon

+0

例外を表示するときにエラー番号10054(既存の接続はリモートホストによって閉じられる) –

答えて

1

私は、そのポートで何も聞いていない(または、受信バックログがいっぱいである)ホスト上のポートにパケットを送信しようとするたびにエラーが発生すると思います。

例外ハンドラのdictMapからエントリを削除して、追加の例外がスローされないようにすることをお勧めします。

+0

実際のコードでは、接続解除されたエントリをdictMapから削除しますが、問題のポートが何も送信しなくなっても例外はスローされ続けます。 –

+1

もう片面が落ちたときに複数のセンドを既に飛行中に持っている可能性はありますか?また、EWOULDBLOCKを返すまでrecvfromを呼び出す必要があります... call selectは高価です - selectを呼び出すたびに1つの結果しか得られません。 – xaxxon

+0

非常に可能です。ソケットバッファがいっぱい(またはどれだけいっぱいになっているか)確認する方法はありますか? –

関連する問題