web-dev-qa-db-fra.com

Socket client / serveur UDP dans Python

Je suis nouveau sur python et sockets et j'essaie d'écrire un socket client/serveur en écho. J'ai écrit le serveur pour que 30% des paquets soient perdus. J'ai programmé mon client pour timeout après une seconde car le paquet pourrait être perdu. Cependant, chaque fois que j'exécute mon socket client, ma sortie est 100% REQUEST TIMED OUT. Je suppose que j'obtiens cette sortie car mon serveur ne reçoit jamais le message. J'ai regardé mon code plusieurs fois et je n'arrive pas à comprendre pourquoi j'obtiens constamment cette sortie. Voici mon code pour mon serveur et mes sockets client. Toute aide serait appréciée.

Socket de serveur:

 # 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) 

Prise client:

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

J'ai testé votre code et il fonctionne comme prévu sur ma machine. Votre problème n'est peut-être pas votre code. Ce pourrait être un pare-feu ou autre chose bloquant tous les paquets sur l'interface de bouclage (127.0.0.1). En fonction de votre système d'exploitation, essayez de tester avec un moniteur de paquets comme Wireshark.

En outre, voici quelques suggestions sur la façon d'améliorer votre code pour être plus Pythonic:

Serveur

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)

Client

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

Voici une alternative avec 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