Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UDP Client/Server Socket in Python

Tags:

python

sockets

I'm new to python and sockets and am trying to write an echoing client/server socket. I have written the server so that 30% of the packets are lost. I programmed my client to timeout after one second since the packet could be lost. However, whenever I run my client socket, my output is 100% REQUEST TIMED OUT. I'm assuming I'm getting this output because my server is never receiving the message. I've looked over my code multiple times and cannot figure out why I am constantly getting this output. Below is my code for my server and client sockets. Any help would be appreciated.

Server Socket:

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

Client Socket:

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
like image 631
user3335367 Avatar asked Jan 12 '15 00:01

user3335367


People also ask

What is UDP socket and explain UDP client server with example?

UDP - User Datagram Protocol sockets It is a connection-less protocol where you directly send packets without have to establish a proper connection. UDP packets have smaller headers compared to TCP headers. Also data communication is faster since no acknowledgement is exchanged for reliable packet delivery.

What is UDP client server?

In UDP, the client does not form a connection with the server like in TCP and instead just sends a datagram. Similarly, the server need not accept a connection and just waits for datagrams to arrive. Datagrams upon arrival contain the address of the sender which the server uses to send data to the correct client.

How do you specify socket type for UDP?

The steps of establishing a UDP socket communication on the server side are as follows: Create a socket with the socket() function; Bind the socket to an address using the bind() function; Send and receive data by means of recvfrom() and sendto().


2 Answers

I tested your code, and it works as expected on my machine. Your issue might not be your code. It could be a firewall or something else blocking all the packets on the loopback interface (127.0.0.1). Depending on your operating system, try testing with a packet monitor like Wireshark.

Also, here are a few suggestions on how to improve your code to be more Pythonic:

Server

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')
like image 134
bsa Avatar answered Oct 22 '22 05:10

bsa


Here is an alternative with 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()
like image 34
Fastidious Avatar answered Oct 22 '22 04:10

Fastidious