实例

#!/usr/bin/env python
#-*- coding:utf-8 -*-
import SocketServer class Myserver(SocketServer.BaseRequestHandler): def handle(self):
conn = self.request
print self.client_address
conn.sendall("我能同时处理多个请求!")
flag = True
while flag:
data = conn.recv(1024)
if data == "exit":
flag = False
else:
conn.sendall(data) if __name__ == "__main__":
server = SocketServer.ThreadingTCPServer(("localhost",8000),Myserver)
server.serve_forever()

client请求原理图

源码解析图

源码

class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass

ThreadingTCPServer

class ThreadingMixIn:
"""Mix-in class to handle each request in a new thread.""" # Decides how threads will act upon termination of the
# main process
daemon_threads = False def process_request_thread(self, request, client_address):
"""Same as in BaseServer but as a thread. In addition, exception handling is done here. """
try:
self.finish_request(request, client_address)
self.shutdown_request(request)
except:
self.handle_error(request, client_address)
self.shutdown_request(request) def process_request(self, request, client_address):
"""Start a new thread to process the request."""
t = threading.Thread(target = self.process_request_thread,
args = (request, client_address))
t.daemon = self.daemon_threads
t.start()

ThreadingMixIn

class TCPServer(BaseServer):

    """Base class for various socket-based server classes.

    Defaults to synchronous IP stream (i.e., TCP).

    Methods for the caller:

    - __init__(server_address, RequestHandlerClass, bind_and_activate=True)
- serve_forever(poll_interval=0.5)
- shutdown()
- handle_request() # if you don't use serve_forever()
- fileno() -> int # for select() Methods that may be overridden: - server_bind()
- server_activate()
- get_request() -> request, client_address
- handle_timeout()
- verify_request(request, client_address)
- process_request(request, client_address)
- shutdown_request(request)
- close_request(request)
- handle_error() Methods for derived classes: - finish_request(request, client_address) Class variables that may be overridden by derived classes or
instances: - timeout
- address_family
- socket_type
- request_queue_size (only for stream sockets)
- allow_reuse_address Instance variables: - server_address
- RequestHandlerClass
- socket """ address_family = socket.AF_INET socket_type = socket.SOCK_STREAM request_queue_size = 5 allow_reuse_address = False def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
"""Constructor. May be extended, do not override."""
BaseServer.__init__(self, server_address, RequestHandlerClass)
self.socket = socket.socket(self.address_family,
self.socket_type)
if bind_and_activate:
try:
self.server_bind()
self.server_activate()
except:
self.server_close()
raise def server_bind(self):
"""Called by constructor to bind the socket. May be overridden. """
if self.allow_reuse_address:
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
self.server_address = self.socket.getsockname() def server_activate(self):
"""Called by constructor to activate the server. May be overridden. """
self.socket.listen(self.request_queue_size) def server_close(self):
"""Called to clean-up the server. May be overridden. """
self.socket.close() def fileno(self):
"""Return socket file number. Interface required by select(). """
return self.socket.fileno() def get_request(self):
"""Get the request and client address from the socket. May be overridden. """
return self.socket.accept() def shutdown_request(self, request):
"""Called to shutdown and close an individual request."""
try:
#explicitly shutdown. socket.close() merely releases
#the socket and waits for GC to perform the actual close.
request.shutdown(socket.SHUT_WR)
except socket.error:
pass #some platforms may raise ENOTCONN here
self.close_request(request) def close_request(self, request):
"""Called to clean up an individual request."""
request.close()

TCPServer

class BaseServer:
timeout = None 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 serve_forever(self, poll_interval=0.5):
"""Handle one request at a time until shutdown. Polls for shutdown every poll_interval seconds. Ignores
self.timeout. If you need to do periodic tasks, do them in
another thread.
"""
self.__is_shut_down.clear()
try:
while not self.__shutdown_request:
r, w, e = _eintr_retry(select.select, [self], [], [],
poll_interval)
if self in r:
self._handle_request_noblock()
finally:
self.__shutdown_request = False
self.__is_shut_down.set()
............
def _handle_request_noblock(self):
"""Handle one request, without blocking. I assume that select.select has returned that the socket is
readable before this function was called, so there should be
no risk of blocking in get_request().
"""
try:
request, client_address = self.get_request()
except socket.error:
return
if self.verify_request(request, client_address):
try:
self.process_request(request, client_address)
except:
self.handle_error(request, client_address)
self.shutdown_request(request)
else:
self.shutdown_request(request) ...........
def finish_request(self, request, client_address):
"""Finish one request by instantiating RequestHandlerClass."""
self.RequestHandlerClass(request, client_address, self) def shutdown_request(self, request):
"""Called to shutdown and close an individual request."""
self.close_request(request)

BaseServer部分

延伸

实现多进程,与多线程同理,不过使用的是ForkingTCPServer()类。

ForkingTCPServer源码:

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

    """Mix-in class to handle each request in a new process."""

    timeout = 300
active_children = None
max_children = 40 def collect_children(self):
"""Internal routine to wait for children that have exited."""
if self.active_children is None:
return # If we're above the max number of children, wait and reap them until
# we go back below threshold. Note that we use waitpid(-1) below to be
# able to collect children in size(<defunct children>) syscalls instead
# of size(<children>): the downside is that this might reap children
# which we didn't spawn, which is why we only resort to this when we're
# above max_children.
while len(self.active_children) >= self.max_children:
try:
pid, _ = os.waitpid(-1, 0)
self.active_children.discard(pid)
except OSError as e:
if e.errno == errno.ECHILD:
# we don't have any children, we're done
self.active_children.clear()
elif e.errno != errno.EINTR:
break # Now reap all defunct children.
for pid in self.active_children.copy():
try:
pid, _ = os.waitpid(pid, os.WNOHANG)
# if the child hasn't exited yet, pid will be 0 and ignored by
# discard() below
self.active_children.discard(pid)
except OSError as e:
if e.errno == errno.ECHILD:
# someone else reaped it
self.active_children.discard(pid) def handle_timeout(self):
"""Wait for zombies after self.timeout seconds of inactivity. May be extended, do not override.
"""
self.collect_children() def process_request(self, request, client_address):
"""Fork a new subprocess to process the request."""
self.collect_children()
pid = os.fork()
if pid:
# Parent process
if self.active_children is None:
self.active_children = set()
self.active_children.add(pid)
self.close_request(request) #close handle in parent process
return
else:
# Child process.
# This must never return, hence os._exit()!
try:
self.finish_request(request, client_address)
self.shutdown_request(request)
os._exit(0)
except:
try:
self.handle_error(request, client_address)
self.shutdown_request(request)
finally:
os._exit(1)

ForkingMixIn

ThreadingTCPServer源码解析的更多相关文章

  1. socketserver源码解析和协程版socketserver

    来,贴上一段代码让你仰慕一下欧socketserver的魅力,看欧怎么完美实现多并发的魅力 client import socket ip_port = ('127.0.0.1',8009) sk = ...

  2. [源码解析] 深度学习分布式训练框架 horovod (4) --- 网络基础 & Driver

    [源码解析] 深度学习分布式训练框架 horovod (4) --- 网络基础 & Driver 目录 [源码解析] 深度学习分布式训练框架 horovod (4) --- 网络基础 & ...

  3. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  4. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  5. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  6. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  7. jQuery2.x源码解析(缓存篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 缓存是jQuery中的又一核心设计,jQuery ...

  8. Spring IoC源码解析——Bean的创建和初始化

    Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

  9. jQuery2.x源码解析(构建篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 笔者阅读了园友艾伦 Aaron的系列博客< ...

随机推荐

  1. Java&Selenium数据驱动【DataProvider+TestNG+Array】

    Java&Selenium数据驱动[DataProvider+TestNG+Array] package testNGWithDataDriven; import java.util.conc ...

  2. 内存泄露检测之mtrace

    ————————————————版权声明:本文为CSDN博主「知耻而后勇的蜗牛」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog ...

  3. SQL Server遇到的错误和有用的tools

    1.The target principal name is incorrect.  Cannot generate SSPI context. 检查IIS的profile,可能是密码错误 2.The ...

  4. 浏览器console中加入jquery,测试选择元素

    一.chrome浏览器F12打开调试界面,在console中输入(firefox同样可以): var jquery = document.createElement('script'); jquery ...

  5. 自己实现dup2

    转自 http://blog.csdn.net/todd911/article/details/11747097 #include <stdio.h> #include <unist ...

  6. Linux下查看文件和文件夹大小 df,du命令

    转自 http://www.cnblogs.com/benio/archive/2010/10/13/1849946.html df可以查看一级文件夹大小.使用比例.档案系统及其挂入点,但对文件却无能 ...

  7. devstack 使用openstack命令报错 The request you have made requires authentication. (HTTP 401) Missing value auth-url required for auth plugin password

    关联错误: The request you have made requires authentication. (HTTP 401) (Request-ID: req-88ad2cba-0f2d-4 ...

  8. PostMan的详细介绍

    无论是接口调试还是接口测试,postman都算的上很优秀的工具,好多接口测试平台.接口测试工具框架的设计也都能看到postman的影子,我们真正了解了这款工具,才可以在这个基础上进行自己的设计和改造. ...

  9. 学习ES7+ES8

    es6 语法:http://es6.ruanyifeng.com/#docs/async    作者:阮一峰 撰文为何 身为一个前端开发者,ECMAScript(以下简称ES)早已广泛应用在我们的工作 ...

  10. C语言和Python语言在存储变量方面的不同

    C语言和Python语言在存储变量方面的不同 众所周知,Python是脚本语言,边解释边执行,而C语言是编译型语言 存储变量: C语言定义变量,变量本身代表的就是大小,任何一个字母或者数字 符号均可以 ...