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, port)
where the host
may be a hostname of an IPv4
address.
For IPv6, a socket address is a 4-tuple
(host, port, flowinfo, scopeid)
.
The flowinfo
filed seems to be still
experimental and should be set to zero for now
(
Flow Labels).
The 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[1]
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 AF_INET
to AF_INET6
.
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 serversocket
module.
For the sequential server, we use socket
.
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:
select
system call
(see
Socket Programming HOWTO)
asyncio
module
(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, jan@newmarch.name
" Network Programming using Java, Go, Python, Rust, JavaScript and Julia"
by
Jan Newmarch
is licensed under a
Creative Commons Attribution-ShareAlike 4.0 International License
.
Based on a work at
https://jan.newmarch.name/NetworkProgramming/
.