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. php自学提升进阶路线

    为了自己对php的系统全面深入的掌握,我通过个人经验,以及搜索网上高手经验,汇总了一份php自我学习路线规划,包括实战演练.学习建议.高手进阶.常见问题和测试总结五块.算是一个系统的学习计划和目标吧. ...

  2. java1234教程系列笔记 S1 Java SE 0101 HelloWorld

    本节分为三讲.java概览,第二节讲了安装jdk 配置环境变量 第三节讲了经典的hello world 1.新建一个txt文本 public class chapter0102{ public sta ...

  3. 【mysql】Infobright和mysql数据入库性能测试

    产生测试文件 测试文件部分内容如下: 产生测试文件代码: package foo; import java.io.File; import java.io.FileWriter; import jav ...

  4. Redis执行Lua脚本的情况

    第一个测试: 往Redis里面存入1000个Hash,每个Hash里面有100个元素(Key 0-99,值是Key^2). PHP代码,执行33s左右 <?php $redis = new Re ...

  5. Ant OOM的问题

    ant 编译的问题 Android编译的有时候会报OOM的错误. 可能是Java的堆大小设置的问题 可在 ant.bat 脚本的  @echo off 语句后面添加: set ANT_OPTS=-Xm ...

  6. SOAOffice和iWebOffice、NTKO的比较及其优势(转)

    http://www.cnblogs.com/liping13599168/articles/1681465.html SOAOffice和iWebOffice.NTKO的比较及其优势 近年来,市场上 ...

  7. VMware10.06精简版安装后台运行

    VMware10.06精简版安装时会出现一个安装功能选择菜单,里面有一条后台运行必选功能,一般人会跳过条.当你打算在服务器上用vmware时,一定要安装后台运行服务,否则你无法换出正在运行的后台虚拟机 ...

  8. 开始python学习了

    今晚折腾了半天,终于在mac上把python开发ide搞好了. 本来是打算使用eclipse+pydev的,结果在eclipse marketplace里面搜索到得pydev插件无法安装,一直是提示网 ...

  9. 线程让出实验【RT-Thread学习笔记 4】

    API: rt_thread_yield 线程函数中调用,本线程释放MCU.如果此时有别的相同优先级的任务整处于等待状态,将获得MCU使用权. 线程让出就是给OS增加一个任务调度的机会. 创建两个线程 ...

  10. delphi中webbrowser的用法

    WebBrowser1.GoHome; //到浏览器默认主页 WebBrowser1.Refresh; //刷新 WebBrowser1.GoBack; //后退 WebBrowser1.GoForw ...