Java NIO中的 ServerSocketChannel 是一个能够监听新进来的TCP链接的通道, 就像标准IO中的ServerSocket同样。ServerSocketChannel类在 java.nio.channels包中。java
经过调用 ServerSocketChannel.open() 方法来打开ServerSocketChannel.服务器
经过调用ServerSocketChannel.close() 方法来关闭ServerSocketChannel. 网络
经过 ServerSocketChannel.accept() 方法监听新进来的链接。当 accept()方法返回的时候,它返回一个包含新进来的链接的 SocketChannel。所以, accept()方法会一直阻塞到有新链接到达。异步
一般不会仅仅只监听一个链接,在while循环中调用 accept()方法. socket
固然,也能够在while循环中使用除了true之外的其它退出准则。spa
ServerSocketChannel能够设置成非阻塞模式。在非阻塞模式下,accept() 方法会马上返回,若是尚未新进来的链接,返回的将是null。 所以,须要检查返回的SocketChannel是不是null.如:code
/** * socket server channel */ @Test public void text2() throws IOException { ServerSocketChannel channel = ServerSocketChannel.open(); //新建channel channel.socket().bind(new InetSocketAddress(9999)); //监听端口 channel.configureBlocking(true); //设置阻塞 while (true) { SocketChannel accept = channel.accept(); //设置为阻塞,则此方法阻塞,直到有链接 //若是设置为非阻塞,须要在这里判断 accept == null? ByteBuffer byteBuffer = ByteBuffer.allocate(1024); accept.read(byteBuffer); byteBuffer.flip(); //反转 while (byteBuffer.hasRemaining()) { //判断 System.err.println((char)byteBuffer.get()); //输出 } } }
Java NIO中的SocketChannel是一个链接到TCP网络套接字的通道。能够经过如下2种方式建立SocketChannel:server
下面是SocketChannel的打开方式:blog
当用完SocketChannel以后调用SocketChannel.close()关闭SocketChannel:ip
要从SocketChannel中读取数据,调用一个read()的方法之一。
首先,分配一个Buffer。从SocketChannel读取到的数据将会放到这个Buffer中。
而后,调用SocketChannel.read()。该方法将数据从SocketChannel 读到Buffer中。read()方法返回的int值表示读了多少字节进Buffer里。若是返回的是-1,表示已经读到了流的末尾(链接关闭了)。
写数据到SocketChannel用的是SocketChannel.write()方法,该方法以一个Buffer做为参数。
注意SocketChannel.write()方法的调用是在一个while循环中的。Write()方法没法保证能写多少字节到SocketChannel。因此,咱们重复调用write()直到Buffer没有要写的字节为止。
能够设置 SocketChannel 为非阻塞模式(non-blocking mode).设置以后,就能够在异步模式下调用connect(), read() 和write()了。
若是SocketChannel在非阻塞模式下,此时调用connect(),该方法可能在链接创建以前就返回了。为了肯定链接是否创建,能够调用finishConnect()的方法。
非阻塞模式下,write()方法在还没有写出任何内容时可能就返回了。因此须要在循环中调用write()。前面已经有例子了,这里就不赘述了。
非阻塞模式下,read()方法在还没有读取到任何数据时可能就返回了。因此须要关注它的int返回值,它会告诉你读取了多少字节。
非阻塞模式与选择器搭配会工做的更好,经过将一或多个SocketChannel注册到Selector,能够询问选择器哪一个通道已经准备好了读取,写入等。Selector与SocketChannel的搭配使用会在后面详讲。
/** * socket channel */ @Test public void test3() throws IOException { SocketChannel channel = SocketChannel.open(); //新建服务端 channel.connect(new InetSocketAddress("127.0.0.1",9999)); //链接服务端地址 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //缓冲区 byteBuffer.put("123".getBytes()); byteBuffer.flip(); //反转 while (byteBuffer.hasRemaining()) { //判断 channel.write(byteBuffer); } }