Python Network Programming Cookbook(Second Edition)
上QQ阅读APP看书,第一时间看更新

How to do it...

As seen in the previous socket server based on ForkingMixIn, ThreadingMixIn socket server will follow the same coding pattern of an echo server except for a few things. First, our ThreadedTCPServer will inherit from TCPServer and TheadingMixIn. This multi-threaded version will launch a new thread when a client connects to it. Some more details can be found at http://docs.python.org/2/library/socketserver.html.

The request handler class of our socket server, ForkingServerRequestHandler, sends the echo back to the client from a new thread. You can check the thread information here. For the sake of simplicity, we put the client code in a function instead of a class. The client code creates the client socket and sends the message to the server.

Listing 2.2 shows a sample code on the echo socket server using ThreadingMixIn as follows:

#!/usr/bin/env python 
# Python Network Programming Cookbook, Second Edition -- Chapter - 2 
# This program is optimized for Python 3.5.2. 
# It may run on any other version with/without modifications. 
# To make it run on Python 2.7.x, needs some changes due to API differences. 
# begin with replacing "socketserver" with "SocketServer" throughout the program. 
# See more: http://docs.python.org/2/library/socketserver.html 
# See more: http://docs.python.org/3/library/socketserver.html 
 
import os 
import socket 
import threading 
import socketserver 
 
SERVER_HOST = 'localhost' 
SERVER_PORT = 0 # tells the kernel to pickup a port dynamically 
BUF_SIZE = 1024 
 
 
def client(ip, port, message): 
    """ A client to test threading mixin server"""     
    # Connect to the server 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.connect((ip, port)) 
    try: 
        sock.sendall(bytes(message, 'utf-8')) 
        response = sock.recv(BUF_SIZE) 
        print ("Client received: %s" %response) 
    finally: 
        sock.close() 
 
 
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): 
    """ An example of threaded TCP request handler """ 
    def handle(self): 
        data = self.request.recv(1024) 
        cur_thread = threading.current_thread() 
        response = "%s: %s" %(cur_thread.name, data) 
        self.request.sendall(bytes(response, 'utf-8')) 
 
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): 
    """Nothing to add here, inherited everything necessary from parents""" 
    pass 
 
 
if __name__ == "__main__": 
    # Run server 
    server = ThreadedTCPServer((SERVER_HOST, SERVER_PORT), 
ThreadedTCPRequestHandler) ip, port = server.server_address # retrieve ip address # Start a thread with the server -- one thread per request server_thread = threading.Thread(target=server.serve_forever) # Exit the server thread when the main thread exits server_thread.daemon = True server_thread.start() print ("Server loop running on thread: %s" %server_thread.name) # Run clients client(ip, port, "Hello from client 1") client(ip, port, "Hello from client 2") client(ip, port, "Hello from client 3") # Server cleanup server.shutdown()