Home Python C C++ Java Contact

How to
Code a TCP & UDP Client-Server - Python

How to Code a TCP & UDP Client-Server - Python

In this tutorial we'll learn how to code a TCP and UDP client and server in python using the socket module in python.
TCP or Transmission Control Protocol is a connection-oriented protocol which provides a reliable connection between the server and the client. While
UDP or User Datagram Protocol is termed as a connectionless protocol.



TCP Server

In order to make a TCP server the following process needs to be involved:

  • Create a socket
  • Bind the socket
  • Make the socket listen for connections
  • Accept a connection
  • Send/Recieve data
  • Close the socket

Let's first import the socket module and declare some varaibles

  


import socket

# Our host, 0.0.0.0 means use any
# interface available on our device
host = '0.0.0.0'

# The port number to listen on
port = 8080

Next we create the server socket

  


print("[$] Creating socket...")
# Create the server socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("[$] Socket created successfully!")

The socket() method of socket is use for creating the socket.
The socket.AF_INET is the address family, it means we want our socket to use IPv4 address, if you want to use IPv6 address, use socket.AF_INET6
The socket.SOCK_STREAM is the socket type, it means we want to use TCP.
Next we bind our socket.

  


print("[$] Binding socket...")
# bind the socket
try:
    server_socket.bind((host, port))
except socket.error as err:
    print(f"[-] Bind failed, {str(err)}")
    exit()
print("[$] Bind complete")

The bind() method is use to bind the socket, we use it to associate host/IP address and port number.
Next we listen for connections.

  


# Put the socket in a listening mode
server_socket.listen(10)

print(f"[$] Server started, listening on {host}:{port}")

As you can see, the listen() method is use to put a socket in a listening mode.
Next we accept any incoming connection and recv some data.

  


# accept any incoming connection
client_socket, client_addr = server_socket.accept()
print(f"[$] Got a new connection from {client_addr[0]}:{client_addr[1]}")

# receive data from client
# maximum buffer size
buffer_size = 4096
data = client_socket.recv(4096).decode()

print(f"[$] Data received: {data}")

The accept() method is use for accepting connections. The accept() method returns the client socket and the client address as a tuple.
Next we used the recv() method on the client_socket to receive data from the client, then we'll use the decode() method to decode the data.



It is very important that you always encode data before sending it out on the network.
And decode it after receiving it from the network.

Since this is just an echo server, we'll just convert the data received from the client then send it back to the client.
After that we'll just close the connection.

  


# send back the same message to the server
client_socket.send(data.upper().encode())
server_socket.close()

TCP Client

Steps of making a TCP client

  • Create a socket
  • Connect to another socket
  • Send/Recieve data
  • Close the socket

Here's our TCP client code:

  


import socket

# host to connect to
host = '127.0.0.1'

# port number to connect on
port = 8080

print('[$] Creating socket...')
# Create the client socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('[$] Socket created successfully!')
print(f'[$] Connecting {host}:{port}...')

# Connect to the server
try:
    client_socket.connect((host, port))
except socket.error as err:
    print(f'[-] Connection to server failed, {err}')
    exit()

print('[$] Connected')

# send some data to the server
data = 'Hello Server'
client_socket.send(data.encode())

# receive data from the server
buffer_size = 4096
data_received = client_socket.recv(buffer_size)

print(f'[$] Data received: {data_received.decode()}')

By now you should be familiar with all the methods we used in the client code, well except for connect() which you can tell what it does, it just connect our socket to the specified host/IP on a port.



UDP Server & Client

In order to code a UDP server or client we don't have to write everything we just have to make some small modification to our TCP server and client code.

UDP Server

Steps:

  • Create a socket
  • Bind the socket
  • Send/Recieve data
  • Close the socket

You can see in the steps we did not include 'listen for connection' and 'accept connection because UDP is a connectionless protocol, connection is needed not in order to send/receive data.
Let's start coding the server now.

  


import socket

# Our host, 0.0.0.0 means use any
# interface available on our device
host = "0.0.0.0"

# The port number to listen on
port = 8080

print("[$] Creating socket...")
# Create the server socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print("[$] Socket created successfully!")
print("[$] Binding socket...")
# bind the socket
try:
    server_socket.bind((host, port))
except socket.error as err:
    print(f"[-] Bind failed, {str(err)}")
    exit()
print("[$] Bind complete")

Note that this time we used socket.SOCK_DGRAM instead of socket.SOCK_STREAM because we're no longer gonna be using TCP so we used socket.SOCK_DGRAM which idicates the socket type to be Datagram(or UDP).
Next we'll receive some data from a client then echo back the same data to the client.

  


# receive data from client
buffer_size = 4096
data = server_socket.recvfrom(buffer_size)

message = data[0].decode()
address = data[1]
print(f"[$] Data received: {message} from {address[0]}:{address[1]}")
# send back the same message to the server
server_socket.sendto(message.upper().encode(), address)
server_socket.close()

Since this is a UDP socket, so we'll not be using the recv() function to recv data, we'll be using the recvfrom() function.
The recvfrom() function is used for receiving data from any client. It returns a 2 tuple, the first one is the actual data from the client, then the second one is also a tuple of the client address, which the first one is the client's IP address and the second is the client's port number.
we also used the sendto() function to send data to a specific address. So here we're echoing back the data to the client that sends us the data from the first place.

UDP Client

Steps:

  • Create a socket
  • Send/Recieve data
  • Close the socket

In UDP, we don;t actually have to connect to the server in order to send data that's why in the list of our steps there's no 'connect to the server'.
Client code:

  


import socket

# host to connect to
host = "127.0.0.1"
# port number to connect on
port = 8080

print("[$] Creating socket...")
# Create the client socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print("[$] Socket created successfully!")

data = "Hello Server"
client_socket.sendto(data.encode(), ((host, port)))

# receive data from the server
buffer_size = 4096
data = client_socket.recvfrom(buffer_size)

message = data[0].decode()
address = data[1]

print(f"[$] Data received: {message} from {address[0]}:{address[1]}")
client_socket.close()