non-blocking IO (non-blocking io)
Linux, you can set the socket to make it non-blocking, when you perform a read operation on a non-blocking socket, the process looks like this
as you can see, when the user process issues a read operation, if the data in kernel is not ready, it does not block the user process, but returns an error immediately. From the user process point of view, it initiates a read operation and does not need to wait, but immediately gets a result. When the user process determines that the result is an error, it knows that the data is not ready, so the user can do something else in the interval between this time and the next time the read query is initiated, or send the read operation directly again. Once the data in the kernel is ready and again receives the system call of the user process, it immediately copies the data to the user's memory (this phase is still blocked) and returns.
That is, after a non-blocking recvform system call, the process is not blocked, the kernel returns to the process immediately, and an error is returned if the data is not ready. After the process returns, it can do something else before initiating the recvform system call. Repeat the above process and iterate through the recvform system calls. This process is often called polling. Poll the kernel data until the data is ready, and then copy the data to the process for data processing. It is important to note that the process of copying data is still a blocked state
Therefore, in non-blocking IO, the user process is actually required to constantly proactively ask kernel data ready to be prepared.
Non-blocking IO example
Service side:
From socket Import *server = socket (af_inet, Sock_stream) server.bind ((' 127.0.0.1 ', 8080)) Server.listen (5) Server.setblocking (False) rlist = []wlist = []while True:try:conn, addr = Server.accept () rlist.append (c Onn) print (rlist) except blockingioerror:del_rlist = [] for sock in Rlist:try: data = SOCK.RECV (1024x768) if not data:del_rlist.append (sock) wlist . Append (sock, Data.upper ()) except blockingioerror:continue except Exception: Sock.close () del_rlist.append (sock) del_wlist = [] for item in Wlist:try : sock = item[0] data = item[1] Sock.send (data) Del_wlist.appe ND (item) except Blockingioerror:pass for item in Del_wlist:wlist.remove (item ) for sock in Del_rlist: Rlist.remove (sock) Server.close ()
Client:
From socket Import *c = socket (af_inet, Sock_stream) c.connect ((' 127.0.0.1 ', 8080)) while True: msg = input ("Please enter information:"). Strip () if not msg: continue c.send (Msg.encode (' Utf-8 ')) data = C.recv (1024x768) print (Data.decode (' Utf-8 ')) C.close ()
But non-blocking IO models are never recommended.
We cannot deny the advantages of being able to do other things while waiting for the task to complete (including submitting other tasks, that is, "backstage" can have multiple tasks at "" and "").
But it's also hard to hide its drawbacks:
1. Cyclic call recv () will significantly push up the CPU occupancy rate; This is why we leave a sentence of Time.sleep (2) in the code, otherwise it is very easy to appear in the low-level host card machine situation 2. The response latency for task completion is increased because each time a read operation is polled, the task may be completed at any time between polling two times. This can result in a decrease in overall data throughput.
In addition, in this scenario recv () is more of a test "operation is complete" role, the actual operating system provides more efficient detection "operation is completed" function of the interface, such as select () multiplexing mode, can detect more than one connection active at a time.
Python concurrent programming: non-blocking IO