Python is simple to build non-blocking single process, select mode, epoll mode service, pythonepoll

Source: Internet
Author: User

Python is simple to build non-blocking single process, select mode, epoll mode service, pythonepoll

Because the content of the articles is often crawled, we will attach the Blog Post URL: occasionally update some wrong data or text. We suggest you go to my blog address: --> click here

See my previous article "python simple setup of blocking single process, multi-process, multi-thread service"

1 single-process server-non-blocking mode

Server:

# Coding = utf-8from socket import * import time # used to store all the new connected sockets, This is the focus of g_socketList = [] def main (): serSocket = socket (AF_INET, SOCK_STREAM) serSocket. setsockopt (SOL_SOCKET, SO_REUSEADDR, 1) localAddr = ('', 7788) serSocket. bind (localAddr) # Here you can modify the value of listen to see different phenomena serSocket. listen (1000 )#. set the socket to non-congested #. this is very important. After it is set to non-congested, if there is no client connection during accept, an exception will occur ,#. so we use try to process this function serSocket. setblocking (False) while True: try: newClientInfo = serSocket. accept () failed t Exception as result: pass else: print (".. the new client is connected.: % s "% str (newClientInfo) # newClientInfo [0] is not blocked here. setblocking (False) # Here we will focus on adding the list g_socketList.append (newClientInfo) # To store the client information to be deleted needDelClientInfoList = [] # here, we will read the socket list cyclically and request whether a client connection exists one by one, this is a simplified version of the select version # but it is the core of understanding the select version for clientSocket, clientAddr in g_socketList: try: recvData = clientSocket. recv (1024) if len (recvData)> 0: print ('recv [% s]: % s' % (str (clientAddr), recvData) else: print ('[% s] client has closed' % str (clientAddr) clientSocket. close () g_needDelClientInfoList.append (clientSocket, clientAddr) failed t Exception as result: pass for needDelClientInfo in needDelClientInfoList: g_socketList.remove (needDelClientInfo) if _ name _ = '_ main _': main ()

Client:

# Coding = utf-8from socket import * import randomimport timeserverIp = raw_input ("Please input. server ip: ") connNum = raw_input (" enter. number of times (for example, 1000): ") g_socketList = [] for I in range (int (connNum): s = socket (AF_INET, SOCK_STREAM) s. connect (serverIp, 7788) g_socketList.append (s) print (I) while True: for s in g_socketList: s. send (str (random. randint (0,100 )))#..... time. sleep (1)

We can see that the key point is that for each stored socket in the for loop, whether there is data sending in the loop request, because the speed is very fast, it looks like multi-process processing.

The disadvantage of this mode is that when there are more and more connections, the for loop polling takes longer and longer. When there are thousands of connections, but only one client actually sends data, the server is still polling one by one to check whether there are any requests. So we have the services of the simplified version of selec model:

2 single-process select TCP Server

The select model and epoll model are common in Multiplexing models. Both are system interfaces provided by the operating system. Of course, the select module of Python is more advanced encapsulation. Network Communication is abstracted by Unix systems as the reading and writing of files. Usually devices are provided by device drivers to know whether their data is available. Device drivers that support blocking operations usually implement a group of their own waiting queues. For example, read/write waiting queues are used to support block or non-block operations required by the upper layer (user layer. If the file resources of the device are available (readable or writable), the process will be notified. Otherwise, the process will sleep and wake up when data is available. The file descriptors of these devices are put in an array, and then traverse the array when the select statement is called. If the file descriptor is readable, the file descriptor is returned. After the traversal, if the available device file descriptor still does not exist, select will let the user process sleep until the system wakes up when the resource is available and traverses the previously monitored array. Each traversal is performed in sequence.

Import selectimport socketimport sysserver = socket. socket (socket. AF_INET, socket. SOCK_STREAM) server. bind ('', 7788) server. listen (5) inputs = [server, sys. stdin] running = Truewhile True: # Call the select function to block waiting for readable, writeable, predictional = select. select (inputs, [], []) # data arrival, loop for sock in readable: # Listen to a new connection if sock = server: conn, addr = server. accept () # socket inputs monitored by select. append (conn) # Listening to the keyboard with the input elif sock = sys. stdin: cmd = sys. stdin. readline () running = False break # There is data arriving at else: # Read the data sent by the Client Connection = sock. recv (1024) if data: sock. send (data) else: # Remove socket inputs from the select listener. remove (sock) sock. close () # if user input is detected to hit the keyboard, exit if not running: breakserver. close ()

The disadvantage of select is that there is a maximum limit on the number of file descriptors that a single process can monitor. in Linux, the limit is generally 1024. You can modify the macro definition to promote and re-compile the kernel, however, this will also reduce the efficiency. Generally, this number has a lot to do with the system memory. You can view the specific quantity in cat/proc/sys/fs/file-max. The default number of 32-bit hosts is 1024. The default value of a 64-bit server is 2048. The socket is scanned sequentially, that is, the round-robin merge method is used, which is less efficient. When there are many sockets, each select () request must be scheduled by traversing FD_SETSIZE sockets. No matter which Socket is active, it must be traversed. This will waste a lot of CPU time.

3 epoll Server

Import socketimport select # create socket s = socket. socket (socket. AF_INET, socket. SOCK_STREAM) # The setting can be repeated. bound information s. setsockopt (socket. SOL_SOCKET, socket. SO_REUSEADDR, 1) # bind the local information s. bind ("", 7788) # changes to passive s. listen (10) # create. epoll object epoll = select. epoll () # Add the created socket to the epoll event listener epoll. register (s. fileno (), select. EPOLLIN | select. EPOLLET) connections ={} addresses ={} # Wait for the client to arrive or pair. send data while True: # epoll. fd scan location. -- if the time-out period is not specified, it is blocked waiting for epoll_list = epoll. poll () # events. determine for fd, events in epoll_list: # if the socket created by the socket is activated if fd = s. fileno (): conn, addr = s. accept () print ('new client arrival % s' % str (addr) # Save the conn and addr information respectively. connections [conn. fileno ()] = conn addresses [conn. fileno ()] = addr # register with epoll the readable event epoll that connects to the socket. register (conn. fileno (), select. EPOLLIN | select elif events = select. EPOLLIN: recvData = connections [fd]. recv (1024) if len (recvData)> 0: print ('recv: % s' % recvData) else: # Remove this connection fd epoll from epoll. unregister (fd) # server side closes the connection fd connections [fd]. close () print ("% s --- offline ---" % str (addresses [fd])

The benefits of epoll are:

1. There is no limit on the maximum number of concurrent connections. The maximum number of data interfaces (FD) that can be opened is greater than 1024.
2. Efficiency Improvement, instead of polling, will not decrease as the number of FD increases. Only the active and available FD can call the callback function. The biggest advantage of epoll is that it only uses your "active" connection and has nothing to do with the total number of connections. Therefore, in the actual network environment, epoll is much more efficient than select and poll.

That is to say, epoll is an event mechanism. Instead of Round Robin from the beginning every time, you can ask each other if a client sends data. Instead, you can ask "client, who has data? If this is the active client, it will "raise your hand", then the epoll function will return the active socket link.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.