When Socketchannel is blocked (default is blocking mode) Read function, does not return 0, blocking mode of Socketchannel, if there is no data readable, or buffer full, it will block until the read conditions are satisfied, So the general blocking mode of read is relatively simple, but the blocking mode of the Socketchannel problem is also obvious. Here I combined based on NIO write FTP server debugging process encountered problems, summed up in the non-blocking scene of read encountered problems. Note: The scene here is based on the client sending data in a blocking socket.
1. When read returns-1
Read returns-1 to indicate that the client's data has been sent and the active close socket is completed. So in this scenario, you need to close the Socketchannel and cancel the key, preferably out of the current function. Note that this time the server will continue to use the Socketchannel to read, and the IO exception "remote host forced to shut down an existing connection" is thrown.
2. When Read returns 0
In fact, read returned 0 There are 3 kinds of cases, one is at a certain moment Socketchannel (note is current) No data can be read, then return 0, followed by bytebuffer position equals limit, That is, bytebuffer remaining is equal to 0, this time will return 0, the last situation is the client's data sent over, this time the client wants to obtain the service side of the feedback call the recv function, if the server continued read, this time will return 0.
Summary: When the client is sending a file, and the size of the unknown, the server how to determine the other side has been sent over. If the simple judgment is equal to 0, it may cause the data sent by the client to be incomplete. So, here add a detection of 0 occurrence of the judgment, to determine whether the client is really the data sent over, of course, this method is more clumsy method, everyone if there is a better way, expect you to give me the answer.
There are similar suggestions on the web, such as custom protocols, file size on the data head, and so on.
Note: There is a problem with this while loop reading, in fact it only has one NIO event notification, and in this process, other events will not be processed in time unless the while end.
Server-side code (unknown size of data sent by client)
<pre name= "code" class= "Java" >package Com.myftpnio.handler;
Import java.io.IOException;
Import Java.nio.ByteBuffer;
Import Java.nio.channels.SelectionKey;
Import Java.nio.channels.Selector;
Import Java.nio.channels.SocketChannel;
Import Com.myftpnio.server.FtpNioServer;
public class ClientHandler implements Niohandler {private Socketchannel SC;
@SuppressWarnings ("unused") private Selector Selector;
Private Bytebuffer buf = bytebuffer.allocate (1024);
Private long sum = 0;
private static int count_zore = 0;
Public ClientHandler (Socketchannel SC, Selector Selector) {This.sc = SC;
This.selector = selector;
@Override public void execute (selectionkey key) {//TODO auto-generated Method stub if (Key.isreadable ()) {
try {while (true) {buf.clear ();
int n = sc.read (BUF);
if (n > 0) {sum = n;
System.out.println ("sum=" + sum + "n=" + N + "" + ftpnioserver.bytebuffertostring (BUF)); else if (n = = 0) {if (count_zore++ < Ftpnioserver.max)
{continue;
else {key.interestops (selectionkey.op_write);
Break
or else if (n = = 1) {System.out.println ("Client close connect");
Sc.close ();
Key.cancel ();
Return
(IOException e) {//processing the captured IO exception System.out.println (E.getmessage ());
try {sc.close ();
catch (IOException E1) {//TODO auto-generated catch block E1.printstacktrace ();
} key.cancel ();
Return
} if (Key.iswritable ()) {try {String ret = ' Hello ' + sc.socket (). Getremotesocketaddress (). toString ();
Bytebuffer send = Bytebuffer.wrap (Ret.getbytes ());
Sc.write (send);
Key.cancel ();
Sc.close ();
ftpnioserver.connum--;
Count_zore = 0;
catch (Exception e) {e.printstacktrace ();
}
}
}
}