Four Ways for python to Realize socket Server Concurrency

  • 2021-08-28 20:30:06
  • OfStack

Multi-process & Multithreading

Server side: Multi-process and multi-thread are opened in the same way.

Disadvantages: < 1 > Due to GIL of Cpython, multiple threads cannot be run in the same time; < 2 > It is impossible to enter a process or thread indefinitely

Solution: Multiprocess, concurrent. futures. ProcessPoolExecutor, Thread Pool


import socket
from multiprocessing import Process
from threading import Thread


class MyTcpServer:
  def __init__(self, ip, port):
    self.ip = ip
    self.port = port
    self.server = socket.socket()
    self.server.bind((self.ip, self.port))
    self.server.listen(5)

  def wait_accept(self):
    conn, addr = self.server.accept()
    return conn, addr

  def handle_request(self, conn):
    while 1:
      try:
        data = conn.recv(1024)
        if not data: break
        conn.send(data.upper())
      except Exception as e:
        print(e)
        break
    conn.close()


if __name__ == '__main__':
  server = MyTcpServer('127.0.0.1', 8888)
  while 1:
    conn, addr = server.wait_accept()
    p = Process(target=server.handle_request, args=(conn, ))	#  Create 1 Processes 
    p.start()	#  Tell the operation to provide and start the process 

Process pool & Thread pool

Asynchronous submission task, support asynchronous receiving return results (submit returns 1 futures object, call add_done_callback method)


import socket
from concurrent.futures import ProcessPoolExecutor
# from concurrent.futures import ThreadPoolExecutor


class MyTcpServer:
  def __init__(self, ip, port):
    self.ip = ip
    self.port = port
    self.server = socket.socket()
    self.server.bind((self.ip, self.port))
    self.server.listen(5)

  def wait_accept(self):
    conn, addr = self.server.accept()
    return conn, addr

  def handle_request(self, conn):
    while 1:
      try:
        data = conn.recv(1024)
        if not data: break
        conn.send(data.upper())
      except Exception as e:
        print(e)
        break
    conn.close()


if __name__ == '__main__':
  server = MyTcpServer('127.0.0.1', 8888)
  pool = ProcessPoolExecutor(5)    # 5 Processes 1 Direct service 

  while 1:
    conn, addr = server.wait_accept()
    pool.submit(server.handle_request, conn)	#  Submit tasks asynchronously 

socketserver

Advantages: Simplify socket server creation process.
Serial and concurrent service modes are provided on the server side (TCPServer, ThreadingTCPServer)
Disadvantages: Concurrency cannot be achieved using multiple processes on windows


import socketserver


class MyTcpHandler(socketserver.BaseRequestHandler):
  def handle(self):		#  Communication loop 
    while 1:
      try:
        data = self.request.recv(1024)
        if not data: break
        self.request.send(data.upper())
      except Exception as e:
        print(e)
        break
    self.request.close()


if __name__ == '__main__':
  ip_port = '127.0.0.1', 8888
  server = socketserver.ThreadingTCPServer(ip_port, MyTcpHandler) #  Asynchronous processing  
  server.serve_forever()		#  Connection loop 

Synergetic process

Advantages: Concurrency is realized in a single thread, IO switching is simulated at the code level, and the program running efficiency is improved


from gevent import spawn, monkey;monkey.patch_all()		#  Monkey patch, patch : Routine IO
import socket


class MyTcpServer:
  def __init__(self, ip, port, my_spawn):
    self.ip = ip
    self.port = port
    self.server = socket.socket()
    self.server.bind((self.ip, self.port))
    self.server.listen(5)
    self.spawn = my_spawn		#  Save spawn Local 

  def wait_accept(self):
    while 1:
      conn, addr = self.server.accept()
      self.spawn(self.handle_request, conn)	#  Detection  handle_request Adj. io

  def handle_request(self, conn):
    while 1:
      try:
        data = conn.recv(1024)
        if not data: break
        conn.send(data.upper())
      except Exception as e:
        print(e)
        break
    conn.close()


if __name__ == '__main__':
  server = MyTcpServer('127.0.0.1', 8888, spawn)
  g1 = server.spawn(server.wait_accept)	#  Detection wait_accept Adj. io
  g1.join()	#  Wait g1 End of the run, that is 1 Direct loop detection io

The above is the python implementation of socket server concurrency 4 ways of details, more information about python socket server concurrency please pay attention to other related articles on this site!


Related articles: