Photo by israel palacio on Unsplash
Socket Programming in Python
4 min read
Python is a versatile programming language that can be used for various projects. In this blog post, we will discuss socket programming in python. We will cover the basics of sockets, and how to use them to create network connections between devices. We will also provide some example code for those who want to try out socket programming in python. So, if you are interested in learning more about sockets, or want to start using them in your Python projects, keep reading!
socket module provides a straightforward interface to the Berkeley sockets API. But it uses Python’s object-oriented style. The
socket() function returns a socket object whose methods implement the various socket system calls.
The primary socket API functions are:
Server socket vs client socket
Sockets can mean subtly different things depending on context. There is a difference between a client socket and a server socket.
A client socket is an endpoint of a conversation. It usually is only used for one exchange or a small set of sequential exchanges, and that is it.
A server socket on the other hand is more like a switchboard operator. It doesn't send or receive any data. It only produces client sockets. Each client socket is created in response to some other client socket doing
connect() to the server. Once a client socket is created, the two clients are free to communicate with each other.
An example of this distinction can be found on your browser. The web browser you operate uses client sockets exclusively. The web server that handles requests from the client uses both server sockets and client sockets.
Echo client and server
Below is the minimum example code. A server that echoes all data it receives back (servicing only one client) and a client that sends data.
import socket QUEUE_SIZE = 5 BUFFER_SIZE = 4096 def serve(host, port): # Create a server socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Bind socket to host and port sock.bind((host, port)) # Officially become a server socket sock.listen(QUEUE_SIZE) # Accept connection from outside client_socket, addr = sock.accept() while True: data = client_socket.recv(BUFFER_SIZE) if not data: break client_socket.sendall(data) # Close the client socket client_socket.close() # Close the server socket sock.close()
A server must perform the sequence
accept(). The server does not
recv() on the socket it is listening on but on the new socket returned by
socket() function takes two parameters: address family and socket types. The address family is usually IPv4 (
socket.AF_INET) or IPv6 (
socket.AF_INET6). Socket types are usually streaming sockets (
socket.SOCK_STREAM) or datagram sockets (
The value passed to
bind() depends on the socket's address family. For
socket.AF_INET (IPv4), it expects a
(host, port) tuple.
host can be a hostname, IP address, or an empty string. The IP address
127.0.0.1 is the standard IPv4 address for the loopback interface, so only processes on the host will be able to connect to the server. If you pass an empty string, the server will accept connections on all available IPv4 interfaces.
listen() can take a parameter called backlog. When a backlog is specified, it tells the system to allow a number of unaccepted connections before refusing new connections. A good number for a backlog is 5 (the typical max). If you write your code correctly, five should be plenty.
import socket BUFFER_SIZE = 4096 def connect(host, port, message): # Create a client socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Connect to a server sock.connect((host, port)) # Send message to the server sock.sendall(bytes(message, "utf-8")) # Capture any information back # from the server data = sock.recv(BUFFER_SIZE) # Close the connection sock.close()
recv operate on network buffers. They do NOT necessarily handle all the bytes you hand them (or expect from them). They return when the network buffers have been filled (
send) or emptied (
recv). They then tell you how many bytes they handled. It is your responsibility to call them again until your message has been completely dealt with.
recv() method receive data from the socket. It returns the number of bytes received, which may be less than the size of the data. It requires the
bufsize parameters to be specified. It is the maximum amount of data to be received at once. As for the value of the
bufsize, the documentation recommended the following:
For best match with hardware and network realities, the value of bufsize should be a relatively small power of 2, for example, 4096.
Typically we set this to 4096 or 8192.
The other side has closed the connection when a
recv returns 0 bytes. You will NOT receive any more data from this connection.
send() method also sends the number of bytes sent, which may be less than the size of the data passed in. To ensure you send all the data, use the
sendall() method instead.
As we have seen, sockets are the fundamental building blocks of network communications. By learning how to use them in Python, we can easily add this powerful tool to our arsenal. With a little practice, you'll be able to build robust client-server applications that can communicate across networks. Thanks for reading!