1. Before starting this chapter, you need to understand the difference between synchronous and asynchronous, blocking and non-blocking:
"Blocking" and "non-blocking" and "synchronous" and "asynchronous" cannot simply be literally understood, providing an answer from a distributed system perspective.
1. Synchronous and asynchronous
Synchronous and asynchronous attention is to the message communication mechanism (synchronous communication/asynchronous Communication)
The so-called synchronization is that when a * call is issued, the * call does not return until the result is obtained. But once the call returns, it gets the return value.
In other words, it is the result of the * caller actively waiting for this * call *.
Instead of async, the call is returned immediately after it isemitted , so no results are returned . In other words, when an asynchronous procedure call is made, the caller does not get the result immediately. Instead, the caller is notified by status, notification, or by a callback function to handle the call after the * call * is issued.
Typical asynchronous programming models like node. js
To cite a popular example:
You call the bookstore boss there is no "distributed System" this book, if it is a synchronous communication mechanism, the bookstore owner will say, you wait, "I check", and then start to check Ah, and so check (maybe 5 seconds, may be a day) to tell you the results (return results).
and the asynchronous communication mechanism, the bookstore owner directly told you I check Ah, check the phone to you, and then directly hung up (do not return the results). And then check it out and he'll call you on his own initiative. Here the boss calls back by "callback" this way.
2. Blocking and non-blocking
Blocking and non-blocking concerns the state of the program when it waits for the call result ( message, return value).
A blocking call means that the current thread is suspended until the call results are returned. The calling thread will not return until the result is obtained.
A non-blocking call means that the call does not block the current thread until the result is not immediately available.
Or the above example,
You call to ask the bookstore owner there is a "distributed System" this book, if you are blocking calls, you will always put yourself "hang" until the book has no results, if the non-blocking call, you don't care if the boss has told you, you have to play the first side, Of course, you'll have to check the boss for a few minutes occasionally.
Here the blocking is independent of the non-blocking and whether synchronous asynchronous. It has nothing to do with how the boss responds to your results.
2. Use forkingmixin in the socket server program:
#-*-Coding:utf-8-*-
# write an asynchronous Python socket server program that does not block when the server handles requests made by the client.
# so find a mechanism to process each client individually,
# The Socketserver module in Python2.7 provides two practical classes: Forkingmixin and ThreadingMixIn,
# Forkingmixin will derive a new process for each client request
#!usr/bin/env Python
# Python Network Programming Cookbook--chapter-1
# Optimized for Python 2.7
# It may run on any other version with/without modifications
Import OS
Import socket
Import threading
Import Socketserver
server_host= ' localhost '
Server_port=0
buf_size=1024
Echo_msg= ' Hello echo server '
Class Forkingclient ():
"" A client test for a forking service ""
def __init__ (Self,ip,port):
Self.sock=socket.socket (Socket.af_inet,socket. SOCK_STREAM)
Self.sock.connect ((Ip,port))
def run (self):
"" Client and server Interaction "" "
Current_process_id=os.getpid ()
print ' pid%s send echo message to server: '%s ' '% (current_process_id,echo_msg)
Sent_data_length=self.sock.send (ECHO_MSG)
Print "Send:%d characters, so far ..."%sent_data_length
RESPONSE=SELF.SOCK.RECV (Buf_size)
Print "pid%s Received:%s"% (current_process_id,response[5:])
def shutdown (self):
"" Clears the client's socket "" "
Self.sock.close ()
Class Forkingserverrequesthandler (Socketserver.baserequesthandler):
def handle (self):
DATA=SELF.REQUEST.RECV (Buf_size)
Current_process_id=os.getppid ()
Response= '%s:%s '% (current_process_id,data)
Print "Server send response [current process id:data]=[%s]"%response
Self.request.send (response)
Return
Class Forkingserver (Socketserver.forkingmixin,socketserver.tcpserver):
"" Nothing can be added here, inheriting the attribute "" "that must be in the parent class
Pass
def main ():
Server=forkingserver ((server_host,server_port), Forkingserverrequesthandler)
Ip,port=server.server_address
Server_thread=threading. Thread (Target=server.serve_forever)
Server_thread.setdaemon (True)
Server_thread.start ()
print ' Server loop run pid:%s '%os.getpid ()
Client1=forkingclient (Ip,port)
Client1.run ()
Client2=forkingclient (Ip,port)
Client2.run ()
Server.shutdown ()
Client1.shutdown ()
Client2.shutdown ()
Server.socket.close ()
If __name__== ' __main__ ':
Main ()
The program consists of 3 parts:
The most work to do to build a socketserver is to define a request-handling (handler) class.
It is a subclass of the Baserequesthandler class in the Socktserver module, and each request handler object processes a client's requests when the client connects to the server.
This is implemented in the handle method of request processing.
Whenever you connect to this server, the TCPServer class passes the correct variables to create a new requesthandler and calls the handle method to process the request.
Here is the server class and main Main method:
Process_request will inherit from ThreadingMixIn or Forkingmixin, create a new thread for each request, and then be called by the thread Finish_request
Operation Result:
2017.07.12 Python network programming using multiplexed sockets I/O