NIO Sokcet是被用于连接到一个TCP网络的Socket。类似于原本的Socket类。以下有两种方法可创建一个SocketChannel。
1.直接调用SocketChannel类中的open();
2.当请求到达ServiceSocketChannel,该类对象会自动创建一个SocketChanel;
SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
关闭SocketChannel
socketChannel.close();
读取SocketChannel
ByteBuffer buf = ByteBuffer.allocate(48); int bytesRead = socketChannel.read(buf);
首先分配一个缓冲区,然后调用read(),可将数据从通道指向的地方读取到缓冲区中。返回的int 表示有多少字节被读取到缓冲区。 如果返回的是-1。表示这个连接已经被关闭了。
写入到SocketChannel。
调用write();
String newData = "New String to write to file..." + System.currentTimeMillis(); ByteBuffer buf = ByteBuffer.allocate(48); buf.clear(); buf.put(newData.getBytes()); buf.flip(); while(buf.hasRemaining()) { channel.write(buf); }
注意写操作是在一个循环当中,这样做不能保证有多少字节被write()方法写入到SocketChannel。因此重复写指导缓冲区没有多余的数据。
非阻塞模式
你可以设置SocketChannel为一个非阻塞模式,当你这样做之后,你能调用connect(),read(),write()这些方法用一种异步的模式。
coonect()
如果SocketChannel是非阻塞模式,你调用了connect()方法。这个方法可能在一个连接被建立之前就返回。为了确定连接是否被建立,你能调用finishConnect()(意思是你能在连接建立之前做一些其他事情。)
socketChannel.configureBlocking(false); socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80)); while(! socketChannel.finishConnect() ){ //wait, or do something else... }
write()
非阻塞的方法可能什么东西都不返回,因此你需要在一个循环中调用write()方法。上面例子已经说明。
read()。
在非阻塞read()方法中可能你也会什么都读不到,因此你需要注意调用方法返回的那个int。
非阻塞模式的选择器。
在非阻塞模式中SocketChannel搭配Selector食用口味更佳。通过注册一个或者多个SocketChannel到选择器当中,你能得到已经准备好读写的选择器,接下来对这个进行详细讲解。
Java NIO ServerSocketChannel
ServerSocketChannel是一个能监听TCP连接的通道。就像ServerSocket一样。
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(9999)); while(true){ SocketChannel socketChannel = serverSocketChannel.accept(); //do something with socketChannel... }
开启一个ServerSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
关闭一个ServerSocketChannel
serverSocketChannel.close();
监听到来的连接。
ServerSocketChannel.accept()这个方法能监听每一个到来的连接,这个方法返回一个SocketChannel。
因此,这个线程会一直阻塞直到一个连接到来。
while(true){ SocketChannel socketChannel = serverSocketChannel.accept(); //do something with socketChannel... }
非阻塞模式
ServerSocketChannel
能被设置为非阻塞模式,在非阻塞模式中,accept()立即返回。因此可能会返回null,如果没有连接到来,你必须确定
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(9999)); serverSocketChannel.configureBlocking(false); while(true){ SocketChannel socketChannel = serverSocketChannel.accept(); if(socketChannel != null){ //do something with socketChannel... } }