python实现select和epoll模型socket网络编程

简介:

这里简单搞搞select和eopll的接口开发 ~


select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实

上从现在看来,这也是它所剩不多的优点之一,现在其实更多的人用epoll,在

python下epoll文档有点少,就先讲究搞搞select ~


select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在

Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一

限制。


说点我的理解,要是用烦了多线程的网络编程,可以试试select的模型。


传递给 select 的参数是几个列表,分别表示读事件、写事件和错误事件。select 方法返回三个列表,其中包含满足条件的对象(读、写和异常)。


服务端的代码:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#coding:utf-8
import  socket,select
import  time
import  os
#xiaorui.cc
host  =  "localhost"
port  =  50000
=  socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((host,port))
s.listen( 5 )
while  1 :
      infds,outfds,errfds  =  select.select([s,],[],[], 5 )
      if  len (infds) ! =  0 :
         clientsock,clientaddr  =  s.accept()
         buf  =  clientsock.recv( 8196 )
         if  len (buf) ! =  0 :
             print  (buf)
             os.popen( 'sleep 10' ).read()                                                                                                      
         clientsock.close()
#     print "no data coming"


客户端的代码:


1
2
3
4
5
6
7
8
9
10
#coding:utf-8
import  socket,select
#xiaorui.cc
host  =  "localhost"
port  =  50000
=  socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))
                                                                                                                                                                                                                                                                                                                                                                                                                                                     
s.send( "coming from select client" )
s.close()



170058459.jpg


一个完成的select的例子:

这里有队列的概念

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#
import  select                                                                                                                                
import  socket
import  Queue
import  time
import  os
#创建socket 套接字
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.setblocking(False)
#配置参数
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR  ,  1 )
server_address= ( '192.168.0.101' , 9999 )
server.bind(server_address)
server.listen( 10 )
inputs = [server]
outputs = []
message_queues = {}
#timeout =  20
while  inputs:
     print  "waiting for next event"
#    readable , writable , exceptional = select.select(inputs, outputs, inputs, timeout)  最后一个是超时,当前连接要是超过这个时间的话,就会kill
     readable , writable , exceptional = select.select(inputs, outputs, inputs)
                                                                                                                                                        
     # When timeout reached , select  return  three empty lists
     if  not (readable or writable or exceptional) :
         print  "Time out ! "
         break ;
     for  in  readable :
         if  is  server:
             #通过inputs查看是否有客户端来
             connection, client_address = s.accept()
             print  "    connection from " , client_address
             connection.setblocking( 0 )
             inputs.append(connection)
             message_queues[connection] = Queue.Queue()
         else :
             data = s.recv( 1024 )
             if  data :
                 print  " received "  , data ,  "from " ,s.getpeername()
                 message_queues[s].put(data)
                 # Add output channel  for  response
                 if  s not  in  outputs:
                     outputs.append(s)
             else :
                 #Interpret empty result  as  closed connection
                 print  "  closing" , client_address
                 if  in  outputs :
                     outputs.remove(s)
                 inputs.remove(s)
                 s.close()
                 #清除队列信息
                 del message_queues[s]
     for  in  writable:
         try :
             next_msg = message_queues[s].get_nowait()
         except Queue.Empty:
             print  " "  , s.getpeername() ,  'queue empty'
             outputs.remove(s)
         else :
             print  " sending "  , next_msg ,  " to " , s.getpeername()
             os.popen( 'sleep 5' ).read()
             s.send(next_msg)
                                                                                                                                                            
     for  in  exceptional:
         print  " exception condition on " , s.getpeername()
         #stop listening  for  input on the connection
         inputs.remove(s)
         if  in  outputs:
             outputs.remove(s)
         s.close()
         #清除队列信息
         del message_queues[s]


关于epoll的方面,大家可以看看这个老外的文档,写不错 ~


select是轮询、epoll是触发式的,所以epoll的效率高。


参考的文档地址:http://scotdoyle.com/python-epoll-howto.html


下面是用epoll实现一个服务端 ~


blog from xiaorui.cc


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import  socket, select
EOL1 = b '\n\n'
EOL2 = b '\n\r\n'
response  = b 'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n'
response += b 'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n'
response += b 'Hello, world!'
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,  1 )
serversocket.bind(( '0.0.0.0' 8080 ))
serversocket.listen( 1 )
serversocket.setblocking( 0 )
epoll = select.epoll()
epoll.register(serversocket.fileno(), select.EPOLLIN)
try :
    connections = {}; requests = {}; responses = {}
    while  True:
       events = epoll.poll( 1 )
       for  fileno, event  in  events:
          if  fileno == serversocket.fileno():
             connection, address = serversocket.accept()
             connection.setblocking( 0 )
             epoll.register(connection.fileno(), select.EPOLLIN)
             connections[connection.fileno()] = connection
             requests[connection.fileno()] = b ''
             responses[connection.fileno()] = response
          elif event & select.EPOLLIN:
             requests[fileno] += connections[fileno].recv( 1024 )
             if  EOL1  in  requests[fileno] or EOL2  in  requests[fileno]:
                epoll.modify(fileno, select.EPOLLOUT)
                connections[fileno].setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK,  1 )
                print( '-' * 40  '\n'  + requests[fileno].decode()[:- 2 ])
          elif event & select.EPOLLOUT:
             byteswritten = connections[fileno].send(responses[fileno])
             responses[fileno] = responses[fileno][byteswritten:]
             if  len(responses[fileno]) ==  0 :
                connections[fileno].setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK,  0 )
                epoll.modify(fileno,  0 )
                connections[fileno].shutdown(socket.SHUT_RDWR)
          elif event & select.EPOLLHUP:
             epoll.unregister(fileno)
             connections[fileno].close()
             del connections[fileno]
finally :
    epoll.unregister(serversocket.fileno())



Epoll的最大好处是不会随着FD的数目增长而降低效率,在select中采用轮询处理,每个fd的处理情况,而epoll是维护一个队列,直接看队列是不是空就可以了。


在这里也推荐大家用epoll写服务端的东西,当然我自己理解的不够好,咱们多交流 !!!




 本文转自 rfyiamcool 51CTO博客,原文链接:http://blog.51cto.com/rfyiamcool/1344824,如需转载请自行联系原作者



相关文章
|
1月前
|
网络协议 安全 网络安全
探索网络模型与协议:从OSI到HTTPs的原理解析
OSI七层网络模型和TCP/IP四层模型是理解和设计计算机网络的框架。OSI模型包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP模型则简化为链路层、网络层、传输层和 HTTPS协议基于HTTP并通过TLS/SSL加密数据,确保安全传输。其连接过程涉及TCP三次握手、SSL证书验证、对称密钥交换等步骤,以保障通信的安全性和完整性。数字信封技术使用非对称加密和数字证书确保数据的机密性和身份认证。 浏览器通过Https访问网站的过程包括输入网址、DNS解析、建立TCP连接、发送HTTPS请求、接收响应、验证证书和解析网页内容等步骤,确保用户与服务器之间的安全通信。
117 3
|
1月前
|
监控 安全 BI
什么是零信任模型?如何实施以保证网络安全?
随着数字化转型,网络边界不断变化,组织需采用新的安全方法。零信任基于“永不信任,永远验证”原则,强调无论内外部,任何用户、设备或网络都不可信任。该模型包括微分段、多因素身份验证、单点登录、最小特权原则、持续监控和审核用户活动、监控设备等核心准则,以实现强大的网络安全态势。
141 2
|
3月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于BP神经网络的苦瓜生长含水量预测模型matlab仿真
本项目展示了基于BP神经网络的苦瓜生长含水量预测模型,通过温度(T)、风速(v)、模型厚度(h)等输入特征,预测苦瓜的含水量。采用Matlab2022a开发,核心代码附带中文注释及操作视频。模型利用BP神经网络的非线性映射能力,对试验数据进行训练,实现对未知样本含水量变化规律的预测,为干燥过程的理论研究提供支持。
|
2月前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
157 2
|
2月前
|
运维 网络协议 算法
7 层 OSI 参考模型:详解网络通信的层次结构
7 层 OSI 参考模型:详解网络通信的层次结构
467 1
|
3月前
|
网络协议 前端开发 Java
网络协议与IO模型
网络协议与IO模型
195 4
网络协议与IO模型
|
3月前
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
199 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
|
3月前
|
机器学习/深度学习 网络架构 计算机视觉
目标检测笔记(一):不同模型的网络架构介绍和代码
这篇文章介绍了ShuffleNetV2网络架构及其代码实现,包括模型结构、代码细节和不同版本的模型。ShuffleNetV2是一个高效的卷积神经网络,适用于深度学习中的目标检测任务。
135 1
目标检测笔记(一):不同模型的网络架构介绍和代码
|
3月前
|
JSON 数据格式 Python
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
本文介绍了如何使用Python的socket模块实现客户端到服务器端的文件传输,包括客户端发送文件信息和内容,服务器端接收并保存文件的完整过程。
223 1
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
|
2月前
|
网络协议 算法 网络性能优化
计算机网络常见面试题(一):TCP/IP五层模型、TCP三次握手、四次挥手,TCP传输可靠性保障、ARQ协议
计算机网络常见面试题(一):TCP/IP五层模型、应用层常见的协议、TCP与UDP的区别,TCP三次握手、四次挥手,TCP传输可靠性保障、ARQ协议、ARP协议

热门文章

最新文章