網絡編程---SocketServer

SocketServer編程

類的繼承關係服務器

編程接口socket

#BaseServer代碼
class BaseServer:
    def __init__(self, server_address, RequestHandlerClass):
        """Constructor.  May be extended, do not override."""
        self.server_address = server_address
        self.RequestHandlerClass = RequestHandlerClass
        self.__is_shut_down = threading.Event()
        self.__shutdown_request = False
    
    def finish_request(self, request, client_address):#處理請求的方法
        """Finish one request by instantiating RequestHandlerClass."""
        self.RequestHandlerClass(request, client_address, self)#RequestHandlerCLass構造

#BaserequestHandler要子類覆蓋的方法
class BaseRequestHandler:
    def __init__(self, request, client_address, server):
        self.request = request
        self.client_address = client_address
        self.server = server
        self.setup()
        try:
            self.handle()
        finally:
            self.finish()

    def setup(self):#每個鏈接初始化
        pass

    def handle(self):#每個處理請求
        pass

    def finish(self):#每個鏈接清理
        pass
#測試代碼
import socketserver
import threading
class MyHandler(socketserver.BaseRequestHandler):
    def handle(self):
        # super().handle()#能夠不調用,父類handler什麼都沒有作
        print('-'*30)
        print(self.server)#服務
        print(self.request)#服務端鏈接請求的socket對象
        print(self.client_address)#客戶端地址
        print(self.__dict__)
        print(self.server.__dict__)

        print(threading.enumerate())
        print(threading.current_thread())
        print('*'*30)

addr = ('10.39.27.2',9999)
server = socketserver.ThreadingTCPServer(addr,MyHandler)

server.serve_forever()#永久

import threading
import logging
import socketserver

FORMAT="%(asctime)s %(threadName)s %(thread)d %(message)s"
logging.basicConfig(level=logging.INFO,format=FORMAT)

class MyHandler(socketserver.BaseRequestHandler):
    def handle(self):
        print(self.request)#服務端負責客戶端鏈接請求的socket對象
        print(threading.enumerate())
        print(threading.current_thread())

        for i in range(3):
            data = self.request.recv(1024)
            logging.info(data)
        logging.info('========end===========')

addr = ('10.39.27.2',9999)
# server = socketserver.ThreadingTCPServer(addr,MyHandler)
server = socketserver.TCPServer(addr,MyHandler)

server.serve_forever()

小結ide

建立服務器須要幾個步驟:
    1.從BaseRequestHandler類派生出子類,並覆蓋其handler()方法來建立請求處理程序類,此方法將處理傳入請求;
    2.實例化一個服務器類,傳參服務器的地址和請求處理類;
    3.調用服務器示例的handler_request()或server_forver()方法;
    4.調用server_close()關閉套接字。

實現EchoServer函數

import threading
from socketserver import ThreadingTCPServer,BaseRequestHandler
import sys

class EchoHandler(BaseRequestHandler):
    def setup(self):
        super().setup()
        self.event = threading.Event()#初始工做

    def handle(self):
        super().handle()

        while not self.event.is_set():
            data = self.request.recv(1024).decode()
            msg = "{} {}".format(self.client_address,data).encode()
            self.request.send(msg)
        print('End')

    def finish(self):
        super().finish()
        self.event.set()

addr = ('0.0.0.0',9999)
server = ThreadingTCPServer(addr,EchoHandler)
server_thread  =threading.Thread(target=server.serve_forever,name='EchoServer',daemon=True)
server_thread.start()

try:
    while True:
        cmd = input('>>>')
        if cmd.strip() == 'quit':
            break
        print(threading.enumerate())
except Exception as e:
    print(e)
except KeyboardInterrupt:
    pass
finally:
    print('exit')
    sys.exit(0)

練習--改寫ChatServer測試

import threading
from socketserver import ThreadingTCPServer,BaseRequestHandler
import sys
import logging

FORMAT = "%(asctime)s %(threadName)s %(thread)d %(message)s"
logging.basicConfig(level=logging.INFO,format=FORMAT)

class ChatHandler(BaseRequestHandler):
    clients = {}

    def setup(self):
        super().setup()
        self.event = threading.Event()
        self.clients[self.client_address]  =self.request

    def handle(self):
        super().handle()
        while not self.event.is_set():
            data = self.request.recv(1024).decode()
            if data == 'quit':
                break
            msg = "{} {}".format(self.client_address,data).encode()
            logging.info(msg)
            for c in self.clients.values():
                c.send(msg)
        print('End')

    def finish(self):
        super().finish()
        self.clients.pop(self.client_address)
        self.event.set()

addr = ('0.0.0.0',9999)
server = ThreadingTCPServer(addr,ChatHandler)
server_thread = threading.Thread(target=server.serve_forever,name='ChatServer',daemon=True)
server_thread.start()

try:
    while True:
        cmd = input('>>>')
        if cmd.strip() == 'quit':
            break
        print(threading.enumerate())
except Exception as e:
    print(e)
except KeyboardInterrupt:
    pass
finally:
    print('exit')
    sys.exit(0)

解決客戶端主動斷開鏈接問題ui

 

import threading
from socketserver import ThreadingTCPServer,BaseRequestHandler
import sys
import logging

FORMAT = "%(asctime)s %(threadName)s %(thread)d %(message)s"
logging.basicConfig(level=logging.INFO,format=FORMAT)

class ChatHandler(BaseRequestHandler):
    clients = {}

    def setup(self):
        super().setup()
        self.event = threading.Event()
        self.clients[self.client_address]  =self.request

    def handle(self):
        super().handle()
        while not self.event.is_set():
            data = self.request.recv(1024).decode()
            print(data,'!!!!!!!!!!!!!!!!!!!!!')#增長
            if data == 'quit':
                break
            msg = "{} {}".format(self.client_address,data).encode()
            logging.info(msg)
            for c in self.clients.values():
                c.send(msg)
            print('###############')#增長
        print('End')

    def finish(self):
        super().finish()
        self.clients.pop(self.client_address)
        self.event.set()

addr = ('0.0.0.0',9999)
server = ThreadingTCPServer(addr,ChatHandler)
server_thread = threading.Thread(target=server.serve_forever,name='ChatServer',daemon=True)
server_thread.start()

try:
    while True:
        cmd = input('>>>')
        if cmd.strip() == 'quit':
            break
        print(threading.enumerate())
except Exception as e:
    print(e)
except KeyboardInterrupt:
    pass
finally:
    print('exit')
    sys.exit(0)

#修改上述代碼中handler()函數的一行代碼便可
將if data =='quit'
修改成 if not data or data =='quit'

總結spa

相關文章
相關標籤/搜索