Nonblocking Io)
In non-blocking modeaccept()
Andread()
During the operation, if the data in the kernel is not ready, it does not block the user process, but immediately returns a message. That is to say, after a read operation is initiated by a process, it does not need to block the wait all the time, but immediately gets a result.
If the data is ready, the data can be read and copied to the user memory. If the result shows that the data is not ready, the process continues.Proactive inquiry
Data preparation is a feature of the non-blocking mode.
The pseudocode is as follows:
{ while(read(socket, buffer) != SUCCESS){ } process(buffer);}
Java synchronous non-blocking mode
As mentioned above, Java Socket is a typical application of blocking mode. Startaccpet()
Andread()
The request will continue to be blocked, but Java providessetSoTimeout()
The method sets the timeout time. If no result is obtained within a fixed period of time, the blocking will end and wait for the next Blocking Training. This achieves non-blocking at the application layer.
In JavasetSoTimeout()
Method:
public synchronized void setSoTimeout(int timeout) throws SocketException { if (isClosed()) throw new SocketException("Socket is closed"); if (timeout < 0) throw new IllegalArgumentException("timeout can‘t be negative"); getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));}
Java synchronous non-blocking mode Encoding
SetsetSoTimeout()
Enable server in blocking modeaccpet()
Andread()
Optimized to non-blocking mode.
Socketserverniolistenandread. Java
Import Org. slf4j. logger; import Org. slf4j. loggerfactory; import Java. io. ioexception; import Java. io. inputstream; import Java. io. outputstream; import java.net. serversocket; import java.net. socket; import java.net. socketexception; import java.net. sockettimeoutexception; /*** <p> * non-blocking io-listener non-blocking-read non-blocking ** @ author niujinpeng * @ date 2018/10/15 */public class socketserverniolistenandread {/*** log */P Rivate static final logger = loggerfactory. getlogger (socketserverniolistenandread. class); Private Static object xwait = new object (); public static void main (string [] ARGs) throws ioexception {serversocket = NULL; try {serversocket = new serversocket (83); serversocket. setsotimeout (100); While (true) {Socket socket = NULL; try {socket = serversocket. accept ();} catch (socket Timeoutexception e) {synchronized (socketserverniolistenandread. xwait) {logger.info ("the task data packet is not received from the underlying layer, waiting for 10 ms, simulating the processing time of event X"); socketserverniolistenandread. xwait. wait (10);} continue;} inputstream input = socket. getinputstream (); outputstream output = socket. getoutputstream (); integer sourceport = socket. getport (); int maxlen = 2048; byte [] contentbytes = new byte [maxlen]; int reallen; stringbuffer Message = new stringbuffer (); // The socket is implemented to receive messages without blocking. setsotimeout (10); bioread: While (true) {try {// when reading, the program will be blocked, the system has prepared the data transmitted from the network. While (reallen = input. read (contentbytes, 0, maxlen ))! =-1) {message. append (new string (contentbytes, 0, reallen);/*** if you receive over, the transfer is complete */If (message. tostring (). endswith ("over") {break bioread ;}} catch (sockettimeoutexception E) {// ============================================== ========================================/// run here, it indicates that this read has not received any data streams. // The main thread can do something here, for example =================================== logger.info ("this time the task data packet is not received from the underlying layer, wait 10 milliseconds to simulate the event Y Processing Time "); Continue ;}// output information logger.info (" the server receives a message from the port "+ sourceport +": "+ message. tostring (); // response output. write ("done! ". Getbytes (); output. close (); input. close (); socket. close () ;}} catch (socketexception | interruptedexception e) {logger. error (E. getmessage (), e);} finally {If (serversocket! = NULL) {serversocket. Close ();}}}}
The above code can implement non-blocking of listening and reading data, but it can only be processed one by one, and multithreading can be used.Slightly improved
.
Socketserverniolistenthread. Java
Import Org. slf4j. logger; import Org. slf4j. loggerfactory; import Java. io. inputstream; import Java. io. outputstream; import java.net. serversocket; import java.net. socket; import java.net. sockettimeoutexception;/*** <p> * non-blocking io-listener non-blocking-read non-blocking * by adding the thread concept, enables the socket server to process multiple socket sockets simultaneously * <p> * in non-blocking mode at the application level. In this case, non-blocking Io can be implemented, however, because the system underlying block synchronous Io is called, * the problem is still not fundamentally solved ** @ author niujinpeng * @ date 2018/10/15 */Public class socketserverniolistenthread {private static object xwait = new object (); Private Static final logger = loggerfactory. getlogger (socketserverniolistenthread. class); public static void main (string [] ARGs) throws exception {serversocket = new serversocket (83); serversocket. setsotimeout (100); try {While (true) {Socket socket = NULL; try {socket = serversocket. ACC EPT ();} catch (sockettimeoutexception E1) {// ============================================== ========================================/// run here, it indicates that this accept has not received any TCP connection // The main thread can do something here, for example ================================ synchronized (socketserverniolistenthread. xwait) {logger.info ("no TCP connection is received from the underlying layer this time. Wait for 10 milliseconds to simulate event x processing time"); socketserverniolistenthread. xwait. wait (10);} continue;} // Of course, the business processing process can be handed over to Thread (the thread pool can be used here), and thread creation is resource-consuming. // Eventually cannot be changed. accept () can only accept socket connections one by one. socketserverthread = new socketserverthread (socket); New thread (socketserverthread ). start () ;}} catch (exception e) {logger. error (E. getmessage (), e);} finally {If (serversocket! = NULL) {serversocket. Close () ;}}}/*** of course, after receiving the socket from the client, the service processing process can be handed over to a thread. * However, it still cannot be changed when the socket is one by one for accept. ** @ Author niujinpeng */class socketserverthread implements runnable {/*** log */Private Static final logger = loggerfactory. getlogger (socketserverthread. class); Private Socket socket; Public socketserverthread (Socket socket) {This. socket = socket ;}@ override public void run () {inputstream in = NULL; outputstream out = NULL; try {In = socket. getinputstream (); out = socket. getoutputst Ream (); integer sourceport = socket. getport (); int maxlen = 2048; byte [] contextbytes = new byte [maxlen]; int reallen; stringbuffer message = new stringbuffer (); // We will collect the following information (set it to a non-blocking mode, so that some other things can be done when you read the information) This. socket. setsotimeout (10); bioread: While (true) {try {While (reallen = in. read (contextbytes, 0, maxlen ))! =-1) {message. append (new string (contextbytes, 0, reallen);/** if we read the "over" keyword, * indicates that all client information is transmitted several times, complete **/If (message. indexof ("over ")! =-1) {break bioread ;}} catch (sockettimeoutexception E2) {// ============================================== ========================================/// run here, it indicates that this read has not received any data streams. // The main thread can do something here, for example =================================== logger.info ("this time the task data packet is not received from the underlying layer, wait 10 milliseconds to simulate the event y Processing Time "); Continue ;}// print the following information: Long threadid = thread. currentthread (). GETID (); logger.info ("server (thread:" + threadid + ") received Information from Port: "+ sourceport +": "+ message); // start sending information out. Write (" Send Response Message! ". Getbytes (); // close out. close (); In. close (); this. socket. close ();} catch (exception e) {logger. error (E. getmessage (), e );}}}
Summary of non-blocking synchronous Mode
The user needs to call it constantly and try to read the data until the read is successful before continuing to process the received data. During the entire Io request process, although the user thread can return immediately after each Io request is initiated, in order to wait for the data, it still needs to round-robin and repeat the request continuously, it consumes a lot of CPU resources. This model is rarely used directly, but non-blocking Io is used in other IO models.
Development is more difficult than blocking I/O models. It is suitable for network application development that has low concurrency and does not require timely response.
This article is based on my blog: Https://www.codingme.net reprint please indicate the source
GitHub Source: https://github.com/niumoo/java-toolbox/
References in this article: Io multiplexing, AIO, bio, NiO, synchronous, asynchronous, blocking and non-blocking
Reference article: 6.2 I/O models
Io communication model (2) Synchronous non-blocking mode NiO (nonblocking Io)