package TestNIO;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class BlockingClient {
public static void main(String[] args) throws IOException {
SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
ByteBuffer buf = ByteBuffer.allocate(1024);
while (inChannel.read(buf) != -1) {
buf.flip();
sChannel.write(buf);
buf.clear();
}
//sChannel.shutdownOutput();
//inChannel.close();
sChannel.close();
while (true) {
System.out.println("死循环");
}
}
}
package TestNIO;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class BlockingServer {
public static void main(String[] args) throws IOException {
ServerSocketChannel ssChannel = ServerSocketChannel.open();
ssChannel.bind(new InetSocketAddress(9898));
FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"),
StandardOpenOption.WRITE, StandardOpenOption.CREATE);
SocketChannel sChannel = ssChannel.accept();
System.out.println("BlockingServer accept");
ByteBuffer buf = ByteBuffer.allocate(1024);
System.out.println("BlockingServer accept1");
int i = 2;
while (sChannel.read(buf) != -1) {
System.out.println("BlockingServer accept"+i++);
buf.flip();
outChannel.write(buf);
buf.clear();
}
System.out.println("already get data, and output to local file");
sChannel.close();
outChannel.close();
ssChannel.close();
}
}
如上,是两个最简单的例子。经过几次 debug,有以下理解(也不知道对不对):
- 先执行服务端,服务端会一直阻塞在
SocketChannel sChannel = ssChannel.accept()这里。 - 再执行客户端,当客户端执行了
SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));以后,服务端不阻塞在SocketChannel sChannel = ssChannel.accept()这里,继续往下执行。 - 当服务端执行到
(sChannel.read(buf)会阻塞在这里,直到客户端执行了一次sChannel.write(buf)后,服务端才会继续往下执行,经过循环,在下一次的(sChannel.read(buf)阻塞。 - 当客户端执行了
sChannel.shutdownOutput()或者sChannel.close()后,服务端不会继续在(sChannel.read(buf)阻塞,而此时返回值为-1,所以退出循环 - 有一点不好理解,就是客户端的 SocketChannel 和服务端 accept 来的 SocketChannel,是同一个东西吗,我在客户端单方面执行了
sChannel.close(),服务端那边的 SocketChannel 还在正常工作吗,假设现在把服务端加点代码:读出所有数据新建那个图片后,再向客户端发送数据,是不是就不能成功了。 - 还有一种情况,万一服务端 单方面 close 了呢( sChannel 或者 ssChannel 两种情况)。