Swiftorial Logo
Home
Swift Lessons
Tutorials
Learn More
Career
Resources

Python Advanced - Networking with Sockets

Introduction to networking with sockets in Python

Networking with sockets is a fundamental aspect of building networked applications. Sockets provide a way to connect two nodes on a network to communicate with each other. This tutorial introduces the basics of networking with sockets in Python, including creating server and client applications.

Key Points:

  • Sockets provide a way to connect two nodes on a network for communication.
  • Python's socket module provides a low-level interface for working with sockets.
  • You can create both server and client applications using sockets.

Creating a Socket

To create a socket in Python, you use the socket module and create a socket object. You need to specify the address family (e.g., AF_INET for IPv4) and the socket type (e.g., SOCK_STREAM for TCP):


import socket

# Create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            

Creating a Server

A server socket binds to a specific IP address and port, listens for incoming connections, and accepts them:


import socket

def start_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(("localhost", 12345))
    server_socket.listen(5)
    print("Server listening on port 12345")
    
    while True:
        client_socket, addr = server_socket.accept()
        print(f"Connection from {addr}")
        client_socket.send(b"Hello from server!")
        client_socket.close()

if __name__ == "__main__":
    start_server()
            

In this example, the server socket binds to localhost on port 12345, listens for incoming connections, and sends a greeting message to the client.

Creating a Client

A client socket connects to a server using the server's IP address and port. After establishing the connection, the client can send and receive data:


import socket

def start_client():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect(("localhost", 12345))
    message = client_socket.recv(1024)
    print(f"Received from server: {message.decode()}")
    client_socket.close()

if __name__ == "__main__":
    start_client()
            

In this example, the client socket connects to the server on localhost port 12345 and receives a greeting message from the server.

Handling Multiple Clients

To handle multiple clients, you can use threading or multiprocessing. Here's an example using threading:


import socket
import threading

def handle_client(client_socket):
    message = client_socket.recv(1024)
    print(f"Received: {message.decode()}")
    client_socket.send(b"Hello from server!")
    client_socket.close()

def start_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(("localhost", 12345))
    server_socket.listen(5)
    print("Server listening on port 12345")
    
    while True:
        client_socket, addr = server_socket.accept()
        print(f"Connection from {addr}")
        client_handler = threading.Thread(target=handle_client, args=(client_socket,))
        client_handler.start()

if __name__ == "__main__":
    start_server()
            

In this example, each client connection is handled in a separate thread, allowing the server to handle multiple clients concurrently.

Sending and Receiving Data

You can send and receive data using the send() and recv() methods. It's important to handle data in chunks if the size is unknown or large:


# Example of sending and receiving data

# Server
import socket

def start_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(("localhost", 12345))
    server_socket.listen(5)
    print("Server listening on port 12345")
    
    while True:
        client_socket, addr = server_socket.accept()
        print(f"Connection from {addr}")
        data = b""
        while True:
            chunk = client_socket.recv(1024)
            if not chunk:
                break
            data += chunk
        print(f"Received: {data.decode()}")
        client_socket.send(b"Data received")
        client_socket.close()

if __name__ == "__main__":
    start_server()

# Client
import socket

def start_client():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect(("localhost", 12345))
    client_socket.sendall(b"Hello from client!" * 100)
    response = client_socket.recv(1024)
    print(f"Received from server: {response.decode()}")
    client_socket.close()

if __name__ == "__main__":
    start_client()
            

In this example, the server receives data in chunks and the client sends a message repeatedly to demonstrate handling larger data sizes.

Summary

In this tutorial, you learned about networking with sockets in Python. Sockets provide a low-level interface for network communication, allowing you to create server and client applications. You explored creating and binding sockets, handling multiple clients with threading, and sending and receiving data. Understanding socket programming is essential for building networked applications and services in Python.