web-dev-qa-db-ja.com

Python UDPクライアント/サーバープログラム、問題

Select()に基づいて再送信するためのタイマーの使用法をテストするために、基本的なクライアント/サーバーエコープログラムを作成しようとしています(ただし、意図したとおりに機能しなかった場合は、デバッグを簡素化するためにそのビットをコメントアウトする必要がありました)。関連するコードのスニペットは次のとおりです。

サーバ:

from socket import *
import sys
import select
address = ('localhost', 6005)
server_socket = socket(AF_INET, SOCK_DGRAM)
server_socket.bind(address)

while(1):
    print "Listening"
    recv_data, addr = server_socket.recvfrom(2048)
    print recv_data
    if recv_data == "Request 1" :
        print "Received request 1"
        server_socket.sendto("Response 1", address)
    Elif recv_data == "Request 2" :
        print "Received request 2"
        data = "Response 2"
        server_socket.sendto(data, address)

クライアント:

from socket import *
import sys
import select

address = ('localhost', 6005)
client_socket = socket(AF_INET, SOCK_DGRAM)

num_retransmits = 0
while(num_retransmits < 60):
    num_retransmits = num_retransmits + 1


    data = "Request 1"
    client_socket.sendto(data, address)
    print "Sending request 1"

    recv_data, addr = client_socket.recvfrom(2048)

    print recv_data, "!!"

クライアントでの出力は単に「Sendingrequest1」であり、recvfrom呼び出し以下でブレークポイントが使用された場合、ブレークポイントに到達しません。ですから、クライアントは何も受け取っておらず、受け取るまで持ちこたえていると思います。一方、サーバーでの出力は次のとおりです。

  • 聞いている
  • リクエスト1
  • リクエストを受信1
  • 聞いている
  • 応答1

などなど

最初のループの後、サーバーは再びループし、RESPONSE 1を出力します。これは、サーバーが要求1を受信し、応答1をクライアントに送信し、ループすることを意味します...しかし、2回目のループの後、応答1はまだですそのソケットに!そのため、recv_dataを出力すると、応答1が出力されます。一方、クライアントはrecv_dataを受信して​​いないため、出力していません。サーバーのソケットのバッファーに残っています。

助けてください-私は他のエコープログラムを見てみましたが、それらはすべてTCPを使用しているようで、かなり簡単です(そして私はほとんど同じ手順に従ったと思います)。理由はわかりません。 UDPプログラムが機能していません。sendall()呼び出しを調べてみましたが、TCPでしか機能しないようです。

10
misaochan

アドレスではなくアドレスに送信する必要があります。

from socket import *
import sys
import select
address = ('localhost', 6005)
server_socket = socket(AF_INET, SOCK_DGRAM)
server_socket.bind(address)

while(1):
    print "Listening"
    recv_data, addr = server_socket.recvfrom(2048)
    print recv_data
    if recv_data == "Request 1" :
        print "Received request 1"
        server_socket.sendto("Response 1", addr)
    Elif recv_data == "Request 2" :
        print "Received request 2"
        data = "Response 2"
        server_socket.sendto(data, addr)
14
Mathias

ここで起こっているのは、サーバーが'Response 1'localhost:6005に送信し、localhost:6005もリッスンしているのですぐに受信することです。

正しいように、サーバーは(address, port)にバインドしてリッスンします。クライアントが最初にバインドせずに接続すると、未使用の(address, port)が自動的に割り当てられます。既知の(address, port)を明示的に設定するためにbindを使用するか、addrによって返されるrecvfromを使用して、クライアントがそれに応答するために使用している(address, port)を判別する必要があります。

2
ephemient

サーバー側の10行目

recv_data、addr = server_socket.recvfrom(2048)

する必要があります

recv_data、addr = server_socket.sendto(2048)

ps>私は初心者です。 = P

1
H_7