Knowledge Points:
Previously written in four ways to achieve the efficiency of the concurrency service is still low, the early server used by the Select and poll mode, select this way is to poll all sockets to see if there is an event, but the length of the list of sockets is limited, and the polling method is inefficient, The poll method only solves the limit of the length of the list of sockets, but it is also a polling method. In the actual scenario, the Linux server adopts the Epoll scheme to implement the concurrent service, it solves the polling of this inefficient way, the use of event notification to tell the application which socket sent the data it is much more efficient than the other four, it is a single process single-threaded way, but is blocked, There are two major features: 1, the Epoll mode will be mapped to the same as the operating system can process the application's specified file descriptor memory space (that is, eliminate the application of the socket file descriptor copy to the operating system), it is neither an application nor the operating system, is two common 2, Client sockets send data, Epoll tells the application using event notification instead of polling all socket lists
1, the Code implementation:
#!/usr/bin/env python#Coding=utf-8#Author: Liu Zhong#DATETIME:2018/8/6 9:24#Software:pycharmImportSocketImportSelectImportRe"""previously written in four ways to achieve the efficiency of the concurrency service is still low, the early server used by the Select and poll mode, select this way is to poll all sockets to see if there are no events, but the list of sockets is limited, and the polling method is inefficient, The poll method only solves the limit of the length of the list of sockets, but it is also a polling method. In the actual scenario, the Linux server adopts the Epoll scheme to implement the concurrent service, it solves the polling of this inefficient way, the use of event notification to tell the application which socket sent the data it is much more efficient than the other four, it is a single process single-threaded way, but is blocked, There are two major features: 1, the Epoll method will map a kernel-like can handle the application of the event 2, the client socket send data, the kernel's file system will be notified by the event notification of the application"""defwebserver (): Web_socket=Socket.socket (socket.af_inet, socket. Sock_stream) Web_socket.bind (('127.0.0.1', 7786)) Web_socket.listen (128) EPL= Select.epoll ()#Create a Epoll objectEpl.register (Web_socket.fileno (), select. Epollin | Select. Epollet)#registering a listener socket with EPLFd_dict = Dict ()#The file descriptor and corresponding socket object that holds the new socket whiletrue:epl_list= Epl.poll ()#By default, gets the list of all sockets registered to the EPL object , the Ganso in the list, and the meta-ancestor values that correspond to each other. #file descriptor and event type for sockets forFD, EventinchEpl_list:#gets the file descriptor and event type of the socket ifFD = = Web_socket.fileno ():#At first, the epl_list must be stored in a listening socket, so the new client link comes in, first determine whether the file descriptor and the listener socket file descriptorNew_socket, New_adress= Web_socket.accept ()#New Client link comes in to plug inFd_dict[new_socket.fileno ()] = New_socket#Store the file descriptor and corresponding socket of the new client socket in the dictionaryEpl.register (New_socket.fileno (), select. Epollin)#registering a new socket in EPL elifevent = = Select. Epollin:#when the listener event is triggered, the client sends the data Try: Data= Fd_dict[fd].recv (1024x768). Decode ('Utf-8') except: Print('client does not send data') Else: ifdata:data1=data.splitlines () Request_url= Re.match (r"[^/]+(/[^ ]*)", data1[0])ifRequest_url:file_name= Request_url.group (1) iffile_name = ='/': file_name='/index.html' Try: Body= Open ('./html'+file_name,'RB') except: Response_head='HTTP 404 Not found/1.1\r\n'Response_head+='\ r \ n'response_body=''fd_dict[fd].send ((Response_head+ response_body). Encode ('Utf-8')) Else: Response_body=Body.read () body.close () Response_head='HTTP ok/1.1\r\n'Response_head+='content-length:%d\r\n'%Len (response_body) Response_head+='\ r \ n'fd_dict[fd].send (Response_head.encode ('Utf-8')+response_body) fd_dict[fd].close ()Else: Fd_dict[fd].close ()#close a new socketEpl.unregister (FD)#Remove the link to the file descriptor from EPL delFD_DICT[FD]#Delete the key value pair for this socketweb_socket.close ()if __name__=='__main__': webserver ()
Web Services-3, epoll efficient implementation of concurrent servers