IO model comparison module implemented and select
1.select, need to traverse the socket list, the waiting queue frequently add removal operations,
2. After data arrives also need to know what all the variables socket to socket data
Two operations consume time increases with the number to be monitored socket is greatly increased,
In consideration only specifies the maximum efficiency can only monitor the 1024 socket
epoll problem to be solved
1. avoid frequent operation of the queue
2. Avoid traverse all socket
For the first question
We look at the treatment of select
while True: r_list, w_list, x_list = select.select (RLIST, wlist, XList, 0.5)
# 0.5 here refers to select poll every 0.5 seconds corresponding socket has not ready
After each treatment once read, you need to repeat the punch used, including the removal process, adding process, the default process will be added to the waiting queue, and blocking the process of living, but the waiting queue update operation is not frequent ,
So the first question
epoll program is taken, it will queue the maintenance and blocked processes two operations split !!!
Related code is as follows
import socket,select server = socket.socket() server.bind(("127.0.0.1",1688)) server.listen(5) # Create epoll event object, the follow-up to monitor the event to which the epoll = select.epoll () # registration server listens fd to wait for read event collection epoll.register (server.fileno (), select.EPOLLIN) # Wait for events the while True: for our sock, Event in epoll.poll (): Pass ``` # Epoll in the register and unregister function is used to maintain the waiting queue # Epoll.poll is used to block the process
Such an action would avoid the need to re-treatment every operational problems waiting queue
For the second question
select the process can not know which socket is the data it needs to traverse
epol To solve this problem, maintain a ready list in the kernel,
1. Create an object epoll, epoll also corresponds to a file, the file system management
2. When execution register, add objects to epoll wait queue of socket
3. When data arrives, CPU executes an interrupt program, copy the data to a socket
4. In epoll, the interrupt program will be executed next epoll object callback function, passing Ready socket object
5. socket, ready to add to the list
6. Wake epoll queue of waiting processes
After the wake-up process, due to the ready list, so no need to traverse the socket, you can deal directly with the ready list
To solve these two problems, the amount of concurrency has been greatly improved, while maintaining the maximum level of thousands of socket
epoll correlation function
Import module select select Import
epoll = select.epoll () to create a epoll objects
epoll.register (file handle, event type) registered to monitor file handle and events
Event Type:
select.EPOLLIN readable event
select.EPOLLOUT can write event
select.EPOLLERR error events
select.EPOLLHUP client disconnection events
epoll.unregister (file handle) destroyed the file handle
epoll.poll (timeout) when a file handle changes will be in the form of a list of active reporting to the user process
timeout to timeout, the default is -1, which waits until the file handle change, if you specify 1, then changes epoll report every 1 second of the current file handles, if no change is returned empty
epoll.fileno () returns the file descriptor epoll control (Return the epoll control file descriptor)
epoll.modfiy (fineno, event) fineno file descriptor for the event type of the event is to modify the action event corresponding to the file descriptor
epoll.fromfd (fileno) to create an object from a specified epoll file descriptor
epoll.close () to close the control object descriptor epoll
Case
Client code
# Coding: UTF-8 # client # Create the client socket object Import socket clientsocket = socket.socket, (socket.AF_INET, socket.SOCK_STREAM) #服务端IP地址和端口号元组 server_address = ('127.0.0.1',1688) #客户端连接指定的IP地址和端口号 clientsocket.connect(server_address) while True: #输入数据 data = raw_input('please input:') if data == "q": break if not data: continue #客户端发送数据 clientsocket.send(data.encode("utf-8")) #客户端接收数据 server_data = clientsocket.recv(1024) print ('客户端收到的数据:',server_data) #关闭客户端socket clientsocket.close()
服务器代码
# coding:utf-8
import socket, select
server = socket.socket()
server.bind(("127.0.0.1", 1688))
server.listen(5)
msgs = []
fd_socket = {server.fileno(): server}
epoll = select.epoll()
# 注册服务器的 写就绪
epoll.register(server.fileno(), select.EPOLLIN)
while True:
for fd, event in epoll.poll():
sock = fd_socket[fd]
print(fd, event)
# 返回的是文件描述符 需要获取对应socket
if sock == server: # 如果是服务器 就接受请求
client, addr = server.accept()
# 注册客户端写就绪
epoll.register(client.fileno(), select.EPOLLIN)
# 添加对应关系
fd_socket[client.fileno()] = client
# 读就绪
elif event == select.EPOLLIN:
data = sock.recv(2018)
if not data:
# 注销事件
epoll.unregister(fd)
# 关闭socket
sock.close()
# 删除socket对应关系
del fd_socket[fd]
print(" somebody fuck out...")
continue
print(data.decode("utf-8"))
# 读完数据 需要把数据发回去所以接下来更改为写就绪=事件
epoll.modify(fd, select.EPOLLOUT)
#记录数据
msgs.append((sock,data.upper()))
elif event == select.EPOLLOUT:
for item in msgs[:]:
if item[0] == sock:
sock.send(item[1])
msgs.remove(item)
# 切换关注事件为写就绪
epoll.modify(fd,select.EPOLLIN)