网络编程---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

相关文章
相关标签/搜索