The Python socket interface is very low level, based directly on the BSD C socket API. This makes it pretty gruesome to work with, just like the C version.
For IPv4, a socket address is a pair
host may be a hostname of an IPv4
For IPv6, a socket address is a 4-tuple
(host, port, flowinfo, scopeid).
flowinfo filed seems to be still
experimental and should be set to zero for now
scopeid can be something like the interface name, I think,
needed for link local addresses.
Python uses the type
socket to connect to a server.
You need to specify the IP protocol,
AF_INET for IPv4 or
AF_INET6 for IPv6, and the socket such as
SOCK_STREAM for TCP.
Next, the connection has to be to a
(address, port) for IPv4
or to a
(address, port, flow info, scope id) tuple for IPv6.
We read strings from stdin. The socket reads and writes are in bytes. The other languages considered here have a default encoding of strings to and from bytes. Python prefers to make it explicit. The topic is discussed further in the chapter on Text but here is given explicit encoding as UTF-8.
The IPv4 client is EchoClient.py illustrates these:
# from https://realpython.com/python-sockets/#echo-client-and-server #!/usr/bin/env python3 import socket import fileinput import sys PORT = 2000 # The port used by the server if len(sys.argv) < 2: print('Usage: comm hostname') exit(1) host = sys.argv with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, PORT)) print('Enter line:', end='', flush=True) for line in sys.stdin: # fileinput.input(): print("Read line '%s'" % line) if line.rstrip() == 'BYE': s.close() exit(0) s.sendall(line.encode('utf-8')) data = s.recv(1024) print("Received '%s'" % str(data, encoding='utf-8')) print('Enter line:', end='', flush=True)
For IPv6, simply change
This will work in cases that do not involve a
scopeid (which will probably only occur if you use
ambiguous link local addresses).
There are two mechanisms to write servers.
One uses the
socket type already considered.
The other uses a slightly higher level
For the sequential server, we use
EchoServer.py illustrates this:
# https://realpython.com/python-sockets/#echo-server # sequential server import socket HOST = '' # INADDR_ANY PORT = 2000 with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() while True: conn, addr = s.accept() with conn: print('Connected by', addr) while True: data = conn.recv(1024) if not data: print('Disconnecting') break conn.sendall(data)
For the multi-threaded server, there are three choices:
selectsystem call (see Socket Programming HOWTO)
asynciomodule (see Streams (coroutine based API) or Python simple socket client/server using asyncio)
The server is MutiEchoServer.py:
# from https://www.techbeamers.com/python-tutorial-write-multithreaded-python-server/ import socket from threading import Thread from socketserver import ThreadingMixIn # Multithreaded Python server : TCP Server Socket Thread Pool class ClientThread(Thread): def __init__(self,ip,port): Thread.__init__(self) self.ip = ip self.port = port print('Connecing') def run(self): while True : data = conn.recv(2048) if not data: print('Disconnecting') break conn.send(data) # Multithreaded Python server : TCP Server Socket Program Stub TCP_IP = '0.0.0.0' TCP_PORT = 2000 BUFFER_SIZE = 20 # Usually 1024, but we need quick response tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) tcpServer.bind((TCP_IP, TCP_PORT)) threads =  while True: tcpServer.listen(4) print("Multithreaded Python server : Waiting for connections from TCP clients...") (conn, (ip,port)) = tcpServer.accept() newthread = ClientThread(ip,port) newthread.start() threads.append(newthread) for t in threads: t.join()
Copyright © Jan Newmarch, firstname.lastname@example.org
Based on a work at https://jan.newmarch.name/NetworkProgramming/ .