1,IO多路复用

三种多路复用的机制:select、poll、epoll

用的多的两个:select和epoll

简单的说就是:
1,select和poll所有平台都支持,epoll只有linux支持
2,select效率不高,epoll效率高
3,IO多路复用用来监听socket对象内部是否变化
4,要调用select模块

什么是文件描述符:

当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。文件描述符的有效范围是 0 到 OPEN_MAX

linux查看OPEN_MAX的方法:ulimit -n。linux默认最大文件描述符为1024,一般可以将它改为65535,可以使用命令ulimit -HSn  65535。也可以保存到/etc/security/ulimit.conf里

python的select函数:

def select(rlist, wlist, elist, timeout=None)->(rl,wl,el)

rlist获取变化的句柄添加到rl中

只要wlist有句柄,都放到wl中

当elist某个句柄发生错误时,放到el中

timeout,如果没有设置超时时间,select一直会卡着,如果设置timeout=1,表示句柄没有变化时,select会卡1秒,一有变化就执行

在socket中

select用来监听sk连接时候的句柄和收发数据的句柄

import socket
import select
sk=socket.socket()
sk.bind(("127.0.0.1",9999))
sk.listen(2)
inputs=[sk]
outputs=[]
msg={}
while True:
rlist,wlist,e=select.select(inputs,outputs,[],1)
print(len(inputs),len(rlist),len(wlist),len(outputs))
'''
只要有连接进来,就接收,只要有收发消息的句柄发生变化,就收消息,
收到消息后可以不直接发送,存到outputs里,wlist==outputs,
只要outputs里有句柄,就交给wlist去循环发送
'''
for r in rlist:
if r==sk:
conn,addr=r.accept()
inputs.append(conn)
else:
try:
rt=r.recv(1024)
outputs.append(r)
print(rt)
msg.setdefault(r, [])
msg[r].append(rt)
except:
inputs.remove(r)
del msg[r]
#上面如果没有数据,这边就一直发数据给客户端,直到客户端接收消息,得到的是一大串
for w in wlist:
for m in msg[w]:
w.sendall(m)
outputs.remove(w) #所以发送完这边要删除句柄,解决了无限发数据的问题

socketserver源码剖析

通过上面的实验得出规律:一开始建立socket对象到listen这几步都没变,直到accept之间在循环使用select检查sk是否变化,如果有新链接进来就accept,之后就能通信了。

import socketserver

class MyServer(socketserver.BaseRequestHandler):

    def handle(self):
# print self.request,self.client_address,self.server
conn = self.request
while True:
recv_data=conn.recv(5) conn.sendall(recv_data) if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
print(server.server_address)
server.serve_forever()

这是socketserver服务器端实现代码

第一步:建立socket对象到listen这几步肯定在创建构造函数的时候已经做掉了。

第二步:因为它是多线程,select查看有sk变动后,每次有连接进来就分配一个线程给sk,然后accept连接

第三步:在accept之后调用socketserver.BaseRequestHandler来收发消息,在调用MySocket的handle,也就是调用BaseRequestHandler的handle

第四步:forever()

ThreadingTCPServer的继承关系:

import socket
import select
import threading def handle(sk):
'''此处发送'''
sk.sendall(bytes("hello",encoding="utf-8")) sk=socket.socket()
sk.bind(("127.0.0.1",9999))
sk.listen(5)
while True:
rlist,w,e=select.select([sk],[],[],1)
for r in rlist:
conn,addr=r.accept()
th=threading.Thread(target=handle,args=(conn,))
th.daemon=False
th.start()
sk.close()

socketserver简化

import socket

sk=socket.socket()
sk.connect(("127.0.0.1",9999))
print(sk.recv(1024))
sk.close()

client

自己实现多线程的socket,socketserver源码剖析的更多相关文章

  1. socketserver 源码剖析:

    socketserver 源码剖析[有图有真相]: (一).Socketserver 内部流程调用图:        详解:  1.self.RequestHandlerClass() = MyCla ...

  2. socketserver源码剖析

    作者:人世间链接:https://www.jianshu.com/p/357e436936bf來源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处 BaseServer 和 B ...

  3. Java多线程9:ThreadLocal源码剖析

    ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...

  4. java多线程17:ThreadLocal源码剖析

    ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...

  5. 第二十四篇、socketserver源码剖析

    这里选择的是python2.7(python3和2.7的源码基本类似) #!/usr/bin/env python # -*- coding:utf-8 -*- import SocketServer ...

  6. socket_server源码剖析、python作用域、IO多路复用

    本节内容: 课前准备知识: 函数嵌套函数的使用方法: 我们在使用函数嵌套函数的时候,是学习装饰器的时候,出现过,由一个函数返回值是一个函数体情况. 我们在使用函数嵌套函数的时候,最好也这么写. def ...

  7. python_way day10 python和其他语言的作用域 、 python2.7多继承和3.5多继承的区别 、 socket 和 socketserver源码(支持并发处理socket,多进程,多线程)

    python_way day10 1.python的作用域和其他语言的作用域 2.python2.7多继承和3.5多继承的区别 3.socket和socketserver源码(并发处理socket) ...

  8. python基础-11 socket,IO多路复用,select伪造多线程,select读写分离。socketserver源码分析

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  9. Python之socketserver源码分析

    一.socketserver简介 socketserver是一个创建服务器的框架,封装了许多功能用来处理来自客户端的请求,简化了自己写服务端代码.比如说对于基本的套接字服务器(socket-based ...

随机推荐

  1. lvs的dr模式分析(二)

      #vim /etc/init.d/lvsdrrip #!/bin/bash #DR server VIP=192.168.46.200 case "$1" in start) ...

  2. 如何解决Oracle RAC 安装集群软件或数据库时无法自动识别节点

    在节点一 grid用户下: $ORACLE_HOME=/u01/app/11.2.0/grid/ [grid@orarac1 /]$ cd /u01/app/11.2.0/grid/oui/bin [ ...

  3. 在CentOS上安装并运行SparkR

    环境配置—— 操作系统:CentOS 6.5 JDK版本:1.7.0_67 Hadoop集群版本:CDH 5.3.0 安装过程—— 1.安装R yum install -y R 2.安装curl-de ...

  4. 报错:org.hibernate.AssertionFailure: null id in com.tt.hibernate.entities.News entry (don't flush the Session after an exception occurs)

    在使用hibernate创建数据库的表格时,出现了如下报错: 十二月 28, 2016 10:17:02 上午 org.hibernate.tool.hbm2ddl.SchemaExport perf ...

  5. [platform]Device和Driver注册顺序

    1. 设备和驱动注册,无论谁先谁后,都可以通过查询总线进行匹配 设备挂接到总线上时,与总线上的所有驱动进行匹配(用bus_type.match进行匹配),如果匹配成功,则调用bus_type.prob ...

  6. 【MySQL】锁问题最佳实践

    最近一段时间处理了较多锁的问题,包括锁等待导致业务连接堆积或超时,死锁导致业务失败等,这类问题对业务可能会造成严重的影响,没有处理经验的用户往往无从下手.下面将从整个数据库设计,开发,运维阶段介绍如何 ...

  7. vs2012 发布网站时,发布目录为空

    当我使用Release Any CPU时为空 使用Release X86就正常发布了 奇怪. 之后再切换回 Release Any CPU时正常发布. 在生成时可以尝试设置好生成配置,先生成,再发布.

  8. [Maven]Maven详解

    转自:http://www.cnblogs.com/hongwz/p/5456578.html 一.前言     以前做过的项目中,没有真正的使用过Maven,只知道其名声很大,其作用是用来管理jar ...

  9. 安卓 JDK、SDK、ADT 区别

    问题一:android软件开发是用java语法,但是为什么开发环境还需要jdk,有android sdk不就可以了吗? 答: 我知道写字要用笔,但为什么还需要笔芯(墨水),有笔杆不就可以了吗? 问题二 ...

  10. 解决 umount 时出现的 "Device is busy"

    1.umount, 老是提示:device is busy, 服务又不能停止的. 可以用"umount -fl"解决! 2.mount的基本用法是? 格式:mount [-参数] ...