python socketserver源码分析

socketserver源码分析

socketserver用于建立服务端,讨论TCPServer,一步步简化代码,分析源码

建立连接
  • __init__,server_bind,server_activate对应打开套接字,绑定ip和port,监听端口
关闭连接
  • handle_request处理一段请求请求后,关闭连接
  • serve_forever启动监听,采用多路复用提高吞吐量,shutdown用来关闭连接;serve_forever阻断当前线程,监听selector,shutdown必须在另一个线程设置__shutdown_request,两个线程采用threading.Event通信
import service as socketserver
from concurrent.futures import ThreadPoolExecutor
import time


def run(socket):
    print('run begin')
    socket.serve_forever(5)
    print('run end')


def shutdown(socket):
    print('shutdown begin')
    time.sleep(1 * 60)
    print('shutdown exec')
    socket.shutdown()
    print('shutdown end')


def main():
    socket = socketserver.TCPServer(('0.0.0.0', 8081), socketserver.BaseRequestHandler)
    with ThreadPoolExecutor(4) as pool:
        pool.submit(run, socket)
        pool.submit(shutdown, socket)


if __name__ == '__main__':
    main()

# 输出
# run begin
# shutdown begin
# shutdown exec
# run end
# shutdown end
处理请求
  • 从selector接受到信号后,调用_handle_request_noblock处理连接请求
  • _handle_request_noblock调用get_request(连接可能是tcp或udp)获取请求数据
  • _handle_request_noblock调用process_request实际处理请求,失败时调用handle_error,shutdown_request关闭请求
处理请求详细
  • process_request先调用finish_request正常处理请求后,再调用shutdown_request关闭请求
  • finish_request调用创建时RequestHandlerClass类,创建实例处理请求,大多设计都将处理连接和处理请求数据分开到两个类,解耦
  • process_request可以放在线程或进程中处理提高并发处理
RequestHandler
  • BaseRequestHandler流程很清晰在构造中__init__中执行setup,handle,finish,执行完即销毁
  • 默认提供BaseRequestHandler及子类的handle没有处理过程,自己必须实现
  • 实现一个简单http请求返回demo
# 服务端
import service as socketserver


class HttpRequestHandle(socketserver.StreamRequestHandler):

    def handle(self):
        data = self.request.recv(1024)
        if data:
            print(data)
        data += b'ok'
        resp = b'HTTP/1.1 200 OK\r\ncontent-type: application/json\r\ndate: Wed, 28 Apr 2021 16:20:04 GMT\r\nserver: socketserver\r\n\r\n{"code":"0000","message":"ok","data":{}}'
        self.request.send(resp)


def service_demo():
    print('service begin')
    socket = socketserver.TCPServer(('0.0.0.0', 8081), HttpRequestHandle)
    socket.serve_forever(1)
    print('service end')


if __name__ == '__main__':
    service_demo()

# 客户端
import http.client
import json


def client_demo():
    client = http.client.HTTPConnection('127.0.0.1', 8081)
    headers = {'test_head': 'nxx'}
    client.request('GET', '/index.html', headers=headers)
    respnese = client.getresponse()
    print(json.loads(respnese.read()))


if __name__ == '__main__':
    client_demo()


# 服务端输出
# service begin
# b'GET /index.html HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nAccept-Encoding: identity\r\ntest_head: nxx\r\n\r\n'

# 客户端输出
# {'code': '0000', 'message': 'ok', 'data': {}}
StreamRequestHandler
  • StreamRequestHandler默认将接受和发送关联到rfile,wfile,可以像读写文件一样处理请求
# 服务端
data = self.rfile.readline()
        while data and data != b'\r\n':
            print(data)
            data = self.rfile.readline()
        resp = b'HTTP/1.1 200 OK\r\ncontent-type: application/json\r\ndate: Wed, 28 Apr 2021 16:20:04 GMT\r\nserver: socketserver\r\n\r\n{"code":"0000","message":"ok","data":{}}'
        self.wfile.write(resp)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值