SocketChannel是一個連接到Tcp網絡套接字的通道。可以通過以下兩種方式創建SocketChannel:
1、打開一個SocketChannel並連接到互聯網上的某台服務器。
2、一個新連接到達ServerSocketChannel時,會創建一個SocketChannel。
打開SocketChannel
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);
首先,分配一個Buffer。從SocketChannel讀取到的數據將會放在這個Buffer中
然后,調用SocketChannel.read(),該方法將數據從SocketChannel讀到Buffer中,read()返回的int值表示讀了多少字節進Buffer里。如果返回的是-1,表示已經讀到了流的末尾(連接關閉了)。
寫入SocketChannel
String newData = "新String寫入file。。。"+System.currentTimeMillis(); ByteBuffer buf = ByteBuffer.allocate(48); buf.clear(); buf.put(newData.getBytes()); buf.flip(); while(buf.hasRemaining()){ channel.write(buf); }
注意SocketChannel.write()方法的調用是一個while循環中的,write()方法無法保證能寫多少字節到SocketChannel。所以,我們重復調用write()直到Buffer沒有要寫的字節為止。
非阻塞模式
可以設置SocketChannel為非阻塞模式(non-blocking mode)設置之后,就可以在異步模式下調用connect(),read()和write()了。
connect()
如果SocketChannel在非阻塞模式下,此時調用connect(),該方法可能在連接建立之前就返回了。為了確定連接是否建立,可以調用finishConnect()的方法。
socketChannel.configureBlocking(false); socketChannel.connect(new InetSocketAddress("http://jenkov.com",80)); while(!socketChannel.finishConnect()){ //do something }
write()
非阻塞模式下,write()在尚未寫入任何內容時就可能返回了。所以需要在循環中調用write()。
read()
非阻塞模式下,read()方法在尚未讀取到任何數據時可能就返回了。所以需要關注它的int返回值,它會告訴你讀取了多少字節。
非阻塞模式與選擇器
非阻塞模式與選擇器搭配會工作的更好,通過一個或多個SocketChannel注冊到Selector,可以詢問選擇器哪個通道已經准備好了讀取,寫入等