socketserver多線程處理

1、簡介

  SocketServer簡化了網絡服務器的編寫。在進行socket建立時,使用SocketServer會大大減小建立的步驟,而且SocketServer使用了select它有5個類:BaseServer,TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer。後4個類是同步進行處理的,另外經過ForkingMixIn和ThreadingMixIn類來支持異步。python

  SocketServer的5個類的繼承關係服務器

 

  SocketServer內部使用 IO多路複用 以及 「多線程」 和 「多進程」 ,從而實現併發處理多個客戶端請求的Socket服務端。即:每一個客戶端請求鏈接到服務器時,Socket服務端都會在服務器是建立一個「線程」或者「進 程」 專門負責處理當前客戶端的全部請求。網絡

  

2、提供的類型

   一是Server類:BaseServer/TCPServer/UDPServer用來接收客戶的請求。TCPServer處理TCP請求,UDPServer處理UDP請求。BaserServer是基類,不能直接使用。TCPServer繼承自BaseServer,UDPServer繼承自TCPServer。多線程

  二是Handler類:BaseRequestHandler/DatagramRequestHandler/StreamRequestHandler用來處理每個客戶請求。通常用使用BaseRequestHandler就行,但StreamRequestHandler/DatagramRequestHandler提供了一些特別的功能,前者用來處理流式(TCP)請求,後者處理數據報(UDP)請求。Server每收到一個客戶請求就會建立一個Handler類示例來處理該請求。默認狀況下,TCPServer/UDPServer是單進程單線程的模型,依次處理每一個客戶請求,一個請求處理完畢才能接着處理下一個請求。併發

  三是MixIn類:ForkingMixIn/ThreadingMixIn用來爲Server提供多進程/多線程併發處理能力的。ForkingMixIn是多進程模型,ThreadingMixin是多線程模型。這裏特別巧妙的是,你只要建立一個類,同時繼承Server類和MixIn類就能自動得到併發處理請求的能力。該模塊自己就直接提供了這種類。異步

class ForkingUDPServer(ForkingMixIn, UDPServer): pass
class ForkingTCPServer(ForkingMixIn, TCPServer): pass

class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass三

 

 3、建立socketserver步驟

  • 必須先建立一個請求處理的類,而且這個類要繼承BaseRequestHandle,並重寫父類中的handle方法
  • 實例化一個server class,而且傳遞server ip 和剛建立的請求處理類給server class
  • 調用server class 對象的 handle_request() 或 server_forever()方法來開始處理請求
  • 關閉請求

  server.handle_request()   只處理一個請求socket

       server.forever()      處理多個請求,一直執行ide

4、事例

  簡單的接收客戶端發送的信息,並將其轉換成大寫,再返回給客戶端this

  服務端: spa

# -*- coding: UTF-8 -*-
import socketserver


class MyTCPHandler(socketserver.BaseRequestHandler):
    """
    The request handler class for our server.

    It is instantiated once per connection to the server, and must
    override the handle() method to implement communication to the
    client.
    """

    def handle(self):
        while True:   # 屢次接收客戶端信息
            # self.request is the TCP socket connected to the client
            self.data = self.request.recv(1024).strip()
            print("{} wrote:".format(self.client_address[0]))
            print(self.data)
            # just send back the same data, but upper-cased
            self.request.sendall(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999

    # Create the server, binding to localhost on port 9999
    server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)

    # Activate the server; this will keep running until you
    # interrupt the program with Ctrl-C
    server.serve_forever()

  客戶端:

# -*- coding: UTF-8 -*-

import socket

client = socket.socket()

client.connect(('localhost', 9999))

while True:

    msg = input('>>:').strip()
    if not msg:
        continue
    else:
        client.send(msg.encode('utf-8'))
        upData = client.recv(1024)
        print(upData.decode())

  

5、多線程處理

  到目前爲止咱們全部的c/s鏈接都同時只能處理一個客戶端請求,多個客戶端請求時,要等前面的客戶端請求關閉後才能執行,包括上面的代碼也是。若是想讓socketserver併發起來, 必須選擇使用如下一個多併發的類:

class socketserver.ForkingTCPServer

class socketserver.ForkingUDPServer

class socketserver.ThreadingTCPServer

class socketserver.ThreadingUDPServer

  只須要改變一個地方就能夠了

server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)

  服務端:

import socketserver


class MyTCPHandler(socketserver.BaseRequestHandler):

    def handle(self):
        while True:
            # self.request is the TCP socket connected to the client
            self.data = self.request.recv(1024).strip()
            print("{} wrote:".format(self.client_address[0]))
            print(self.data)
            # just send back the same data, but upper-cased
            self.request.sendall(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999
    server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()
相關文章
相關標籤/搜索