web-dev-qa-db-ja.com

UDPクライアント/サーバーソケットPython

python and socketsが初めてで、エコーするクライアント/サーバーソケットを記述しようとしています。パケットの30%が失われるようにサーバーを記述しました。クライアントをタイムアウトにプログラムしました。しかし、クライアントソケットを実行すると、出力は100%REQUEST TIMED OUTになります。サーバーがメッセージを受信しないため、この出力を取得していると想定しています。私のコードを何度も調べたが、なぜこの出力を常に得ているのか理解できない。

サーバーソケット:

 # We will need the following module to generate randomized lost packets
    import random
    from socket import *

    # Create a UDP socket
    # Notice the use of SOCK_DGRAM for UDP packets
    serverSocket = socket(AF_INET, SOCK_DGRAM)

    # Assign IP address and port number to socket
    serverSocket.bind(('', 12000))

    while True:
        # Generate random number in the range of 0 to 10
        Rand = random.randint(0, 10)

        # Receive the client packet along with the address it is coming from
        message, address = serverSocket.recvfrom(1024)

        # Capitalize the message from the client
        message = message.upper()

        # If Rand is less is than 4, we consider the packet lost and do notrespond
        if Rand < 4:
            continue

        # Otherwise, the server responds
        serverSocket.sendto(message, address) 

クライアントソケット:

import time
from socket import *

pings = 1

#Send ping 10 times 
while pings < 11:  

    #Create a UDP socket
    clientSocket = socket(AF_INET, SOCK_DGRAM)

    #Set a timeout value of 1 second
    clientSocket.settimeout(1)

    #Ping to server
    message = 'test'

    addr = ("127.0.0.1", 12000)

    #Send ping
    start = time.time()
    clientSocket.sendto(message, addr)

    #If data is received back from server, print 
    try:
        data, server = clientSocket.recvfrom(1024)
        end = time.time()
        elapsed = end - start
        print data + " " + pings + " "+ elapsed        

    #If data is not received back from server, print it has timed out  
    except timeout:
        print 'REQUEST TIMED OUT'

    pings = pings - 1
14
user3335367

私はあなたのコードをテストしましたが、私のマシンでは期待通りに動作します。あなたの問題はあなたのコードではないかもしれません。ファイアウォールまたはループバックインターフェイス(127.0.0.1)上のすべてのパケットをブロックする何かである可能性があります。オペレーティングシステムに応じて、Wiresharkのようなパケットモニターでテストしてみてください。

また、コードをよりPythonicに改善する方法に関するいくつかの提案があります。

サーバー

import random
import socket

server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('', 12000))

while True:
    Rand = random.randint(0, 10)
    message, address = server_socket.recvfrom(1024)
    message = message.upper()
    if Rand >= 4:
        server_socket.sendto(message, address)

クライアント

import time
import socket

for pings in range(10):
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    client_socket.settimeout(1.0)
    message = b'test'
    addr = ("127.0.0.1", 12000)

    start = time.time()
    client_socket.sendto(message, addr)
    try:
        data, server = client_socket.recvfrom(1024)
        end = time.time()
        elapsed = end - start
        print(f'{data} {pings} {elapsed}')
    except socket.timeout:
        print('REQUEST TIMED OUT')
27
bsa

Asyncioの代替手段を次に示します。

import asyncio
import random

class EchoServerProtocol:
    def connection_made(self, transport):
        self.transport = transport

    def datagram_received(self, data, addr):
        message = data.decode()
        print('Received %r from %s' % (message, addr))
        Rand = random.randint(0, 10)
        if Rand >= 4:
            print('Send %r to %s' % (message, addr))
            self.transport.sendto(data, addr)
        else:
            print('Send %r to %s' % (message, addr))
            self.transport.sendto(data, addr)


loop = asyncio.get_event_loop()
print("Starting UDP server")

# One protocol instance will be created to serve all client requests
listen = loop.create_datagram_endpoint(
    EchoServerProtocol, local_addr=('127.0.0.1', 12000))
transport, protocol = loop.run_until_complete(listen)

try:
    loop.run_forever()
except KeyboardInterrupt:
    pass

transport.close()
loop.close()
2
Fastidious