Credit: Luther Blissett
Assuming you’re using the Internet to communicate:
import socket # Create a socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Ensure that you can restart your server quickly when it terminates sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Set the client socket's TCP "well-known port" number well_known_port = 8881 sock.bind(('', well_known_port)) # Set the number of clients waiting for connection that can be queued sock.listen(5) # loop waiting for connections (terminate with Ctrl-C) try: while 1: newSocket, address = sock.accept( ) print "Connected from", address # loop serving the new client while 1: receivedData = newSocket.recv(1024) if not receivedData: break # Echo back the same data you just received newSocket.send(receivedData) newSocket.close( ) print "Disconnected from", address finally: sock.close( )
Setting up a server takes a bit more work than setting up a client.
We need to bind
to a well-known port that clients
will use to connect to us. Optionally, as we do in this recipe, we
can set
SO_REUSEADDR
so we can restart the server when it terminates without waiting for a
few minutes, which is quite nice during development and testing. We
can also optionally call listen
to control the
number of clients waiting for connections that can be queued.
After this preparation, we just need to loop, waiting for the
accept
method to return; it returns a new socket object already connected to
the client and the client’s address. We use the new
socket to hold a session with a client, then go back to our waiting
loop. In this recipe, we just echo back the same data we receive from
the client.
The SocketServer
module lets us perform the same task in
an object-oriented way. Using it, the recipe becomes:
import SocketServer class MyHandler(SocketServer.BaseRequestHandler): def handle(self): while 1: dataReceived = self.request.recv(1024) if not dataReceived: break self.request.send(dataReceived) myServer = SocketServer.TCPServer(('',8881), MyHandler) myServer.serve_forever( )
One handler object is instantiated to serve each connection, and the
new socket for that connection is available to its
handle
method (which the server calls) as
self.request
.
Using the SocketServer
module instead of the
lower-level socket
module is particularly
advisable when we want more functionality. For example, to spawn a
new and separate thread for each request we serve, we would need to
change only one line of code in this higher-level solution:
myServer = SocketServer.ThreadingTCPServer(('',8881), MyHandler)
while the socket-level recipe would need substantially more recoding to be transformed into a similarly multithreaded server.
Recipe 10.2; documentation for the standard
library module socket
in the Library Reference; Perl Cookbook Recipe 17.2.
Get Python Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.