Python攻克之路-socketserver模块

SocketServer是python的一个网络服务器框架,可以减少开发人员编写网络服务器程序的工作量。
分析:虽然用Python编写的网络唾弃很方便,但复杂一点的网络唾弃还是使用现成的框架比较好,这样就专心于事务逻辑,而不是套接接字的各种细节,socketserver模块化了编写网络服务程序的任务.同时socketserver模块也是Python标准库中很多服务框架的基础
socketserver模块可以简化网络服务器的编写,Python把网络服务抽象成两个主要的类,一个Server类,用于处理连接相关的网络操作,另外一个则是RequestHandler类,用于处理数据相关的操作.并且提供两个MixIn类,用于扩展Server,实现进程多线程

 

1.实例
server实现接收多并发

[root@node2 socketserver]# cat server.py  #实现有多个client进行连接聊天
#!/usr/local/python3/bin/python3
import socketserver
class MyServer(socketserver.BaseRequestHandler): #自定义一个类,而且要继承一个类

    def handle(self):                            #逻辑都放在handle方法中
        print("starting server..")
        while True:
            conn = self.request                  #client传过来的sk,相当于conn = sk.accept()
            print(self.client_address)
            while True:
                client_data=conn.recv(1024)      #收
                print(str(client_data,"utf8"))
                print('waiting...')
                conn.sendall(client_data)        #发,回写
            conn.close()

if __name__=='__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8091),MyServer) #封装好socket要写的部分,进行调用
    server.serve_forever()     #启动

[root@node2 socketserver]# cat client.py 
#!/usr/local/python3/bin/python3
import socket

ip_port = ('127.0.0.1',8091)
sk = socket.socket()
sk.connect(ip_port)
print('starting client...')
while True:
    inp = input('>>> ')
    sk.sendall(bytes(inp,'utf8'))
    if inp == 'exit':
        break
    server_response=sk.recv(1024)
    print(str(server_response,'utf8'))
sk.close()

测试

[root@node2 socketserver]# python3 server.py 
starting server..
('127.0.0.1', 54978)
starting server..
('127.0.0.1', 54980)
starting server..
('127.0.0.1', 54982)
client1
waiting...
client2
waiting...
client3
waiting...
[root@node2 socketserver]# python3 client.py 
starting client...
>>> client1
client1
[root@node2 socketserver]# python3 client.py 
starting client...
>>> client2
client2
[root@node2 socketserver]# python3 client.py 
starting client...
>>> client3
client3

server实现多并发聊天

[root@node2 socketserver]# cat server.py 
#!/usr/local/python3/bin/python3
import socketserver
class MyServer(socketserver.BaseRequestHandler):

    def handle(self):
        print("starting server..")
        while True:
            conn = self.request
            print(self.client_address)
            while True:
                client_data=conn.recv(1024)
                print(str(client_data,"utf8"))
                print('waiting...')
                server_response=input(">>> ")                #####
                conn.sendall(bytes(server_response,"utf8"))
                conn.sendall(client_data)
            conn.close()

if __name__=='__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8098),MyServer) #实际是封装连接
    server.serve_forever()                                                #实际是启动逻辑
注:真正实际并发的是ThreadingTCPServer类中继承的ThreadingMixIn,建立连接的过程是继承TCPServer类

  

2.代码执行过程
a.先加载模块,到加载类,但是并没有被执行

import socketserver
class MyServer(socketserver.BaseRequestHandler): #自定义一个类,而且要继承一个类
    def handle(self):

b.真正开始执行,实例化出一个对象,实际也是执行init方法

server = socketserver.ThreadingTCPServer(('127.0.0.1',8091),MyServer) #封装好socket要写的部分,进行调用

c. 找到类ThreadingTCPServer,有两个父类ThreadingMinIn, TCPServer

class ThreadingTCPServer(ThreadingMinIn, TCPServer): pass

d.父类TCPServer中有init方法
分析:需要传入参数server_address是ip和port,RequestHandlerClass是类,在init中有创建socket的,而且在TCPServer中,
还有一个父类BaseServer而且还有init方法

(1).BaseServer.__init__(self,server_address,RequestHandlerClass)
(2).self.socket = socket.socket(self.address_family,self.socket_type)
(3).server_bind绑定ip地址和端口
(4).server_activate侦听端口,默认是5个连接
(5).出现错误会执行server_close(),实际是socket.close()关闭

e.执行server.serve_forever()

(1).调用的是BaseServer类,找到serve_forever,真正执行是self.handle_request_noblock()
(2).request, client_address = self.get_request() #request相当于conn,客户端的地址整行代码相当于conn,addr = sk.accept()
(3).正常会执行self.process_request(request,client_address)
(4).执行process_request(在ThreadingMixIn类,相应的创建多线程
(5).到类BaseSever中的init,self.RequestHandlerClass = RequestHandleClass相当于定到自定义的类MyServer下
(6).handle的执行在于class MyServer(socketserver.BaseRequestHandler)中继承的类socketserver.BaseRequestHandler,
    内部就有handle的方法
(7).在BaseRequestHandler中的init方法,执行self.setup(),实际是取决于自定义的方法

f.MyServer中写handle,实际是调用父类中的handle,一旦子类把父类的方法覆盖后,都走子类,当再调用self.handle时,父类中def handle(self):是pass,就会执行子类的MyServer中的方法,子类已经重写了handle方法
g.ThreadingTCPServer类中继承的ThreadingMixIn类的执行

 

3.SocketServer类
主要5个server类:BaseServer,TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer,除了BaseServer,其他类都能够直接使用
BaseServer: 是一个原生类,对某些方法(如server_bind)进行覆盖(子类重写),有process_request,serve_forever等方法
TCPServer: 继承了BaseServer,然后创建socket,绑定端口和ip等TCP的流程实现
UDPSever: 与TCPServer类似
UnixStreamServer:继承TCPServer类,而且只差一个参数adddress_family = socket.AF_UNIX
UnixDatagramServer:继承UDPServer类,而且只差一个参数adddress_family = socket.AF_UNIX

其他server类:
ForkingMixIn: 创建进程

 

4.创建一个socketserver的步骤
(1).First, you must create a request handler class by subclassing the BaseRequestHandler class and overriding its
handle() method;this method will process incoming requsts. 重写一个类并继承BaseRequestHandler
(2).Second, you must instantiate one of the server classes, passing it the server's address and the requst handler class.
把参数实例一个对象,并传递参数,也就是调用server类,有一个server类,实际是使用TCPServer,UDPServer,ThreadingTCPServer,ThreadingUDPServer,在这里实例化一个对象
(3).Then,call the handle_request() or serve_forever() method of the server object to process one or many requests.
调用handle_request()和serve_forever()去处理请求
(4).Finally,call server_close() to close the socket. 关闭

 

转载于:https://www.cnblogs.com/reid21/articles/9065717.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值