Java NIO系列教程(八) SocketChannel

原文鏈接? ? ?作者:Jakob Jenkov ? ??譯者:鄭玉婷 ? ? ?校對:丁一

Java NIO中的SocketChannel是一個連接到TCP網絡套接字的通道??梢酝ㄟ^以下2種方式創建SocketChannel:

  1. 打開一個SocketChannel并連接到互聯網上的某臺服務器。
  2. 一個新連接到達ServerSocketChannel時,會創建一個SocketChannel。

打開 SocketChannel

下面是SocketChannel的打開方式:

SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));

關閉 SocketChannel

當用完SocketChannel之后調用SocketChannel.close()關閉SocketChannel:

socketChannel.close();

從 SocketChannel 讀取數據

要從SocketChannel中讀取數據,調用一個read()的方法之一。以下是例子:

ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf);

首先,分配一個Buffer。從SocketChannel讀取到的數據將會放到這個Buffer中。

然后,調用SocketChannel.read()。該方法將數據從SocketChannel 讀到Buffer中。read()方法返回的int值表示讀了多少字節進Buffer里。如果返回的是-1,表示已經讀到了流的末尾(連接關閉了)。

寫入 SocketChannel

寫數據到SocketChannel用的是SocketChannel.write()方法,該方法以一個Buffer作為參數。示例如下:

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);
}

注意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() ){
    //wait, or do something else...
}

write()

非阻塞模式下,write()方法在尚未寫出任何內容時可能就返回了。所以需要在循環中調用write()。前面已經有例子了,這里就不贅述了。

read()

非阻塞模式下,read()方法在尚未讀取到任何數據時可能就返回了。所以需要關注它的int返回值,它會告訴你讀取了多少字節。

非阻塞模式與選擇器

非阻塞模式與選擇器搭配會工作的更好,通過將一或多個SocketChannel注冊到Selector,可以詢問選擇器哪個通道已經準備好了讀取,寫入等。Selector與SocketChannel的搭配使用會在后面詳講。

原創文章,轉載請注明: 轉載自并發編程網 – www.shiekolong579.icu本文鏈接地址: Java NIO系列教程(八) SocketChannel


FavoriteLoading添加本文到我的收藏
  • Trackback 關閉
  • 評論 (9)
    • 宅男小何
    • 2013/06/20 12:34下午

    客戶端其實直接用socket更簡單,服務器端用nio,O(∩_∩)O哈哈~

  1. Java NIO中的 ServerSocketChannel 是一個可以監聽新進來的TCP連接的通道, 就像標準IO中的ServerSocket一樣。ServerSocketChannel類在 java.nio.channels包中。

    • 壹ban壹伴
    • 2014/04/16 5:48下午

    我想問一下用 socketchannel 連接 serversocket 可以嗎?意思是可以通訊嗎,我試了一下好像不可以
    服務端代碼
    ServerSocket ss = new ServerSocket(9999);
    System.out.println(“服務端開啟…..”);
    while (true) {
    Socket s = ss.accept();
    String ip = s.getInetAddress().getHostAddress();
    System.out.println(ip + “…..connected”);
    SocketChannel channel = s.getChannel();
    ByteBuffer buff = ByteBuffer.allocate(48);
    int len = channel.read(buff);
    while (len != -1) {
    buff.flip();
    System.out.println(buff.get());
    channel.read(buff);
    }
    s.close();// 關閉客戶端.
    客戶端代碼
    SocketChannel socketChannel;
    try {
    socketChannel = SocketChannel.open();
    socketChannel.connect(new InetSocketAddress(“127.0.0.1”, 9999));
    String newData = “test……..” + System.currentTimeMillis();
    ByteBuffer buf = ByteBuffer.allocate(48);
    buf.clear();
    buf.put(newData.getBytes());
    while(buf.hasRemaining()) {
    socketChannel.write(buf);
    }
    System.out.println(“客戶端發送完畢”);

    難道一定要配套使用嗎?????

      • sayhellotojava
      • 2017/10/20 5:57下午

      你的SocketChannel channel = s.getChannel();這里會返回null的,Socket的getChannel方法里面說了,創建SoketChannel實例需要通過ServerSocketChannel的accept方法或者SocketChannel的open方法,因此,你后面的int len = channel.read(buff);會NullPointException的

    • 小小龍
    • 2015/02/16 11:54上午

    我覺得應該在這句話”如果返回的是-1,表示已經讀到了流的末尾(連接關閉了)。” 后面加一句:這個時候應該調用SocketChannel.close(),關閉channel;不然會不斷執行read方法。

    我被這個問題搞了一天半。郁悶啊。

    • hl174
    • 2016/04/25 11:15下午

    buf.clear();
    buf.put(newData.getBytes());

    buf.flip();

    while(buf.hasRemaining()) {
    channel.write(buf);
    }

    這里為嘛也要調用buf.flip()

      • kimulsanne
      • 2016/09/30 10:03上午

      為了將Buffer從寫模式轉換為讀模式。

    • zhoulin
    • 2017/10/22 11:45上午

    劉德華

您必須 登陸 后才能發表評論

return top

合乐彩票app下载 yno| 7yh| ne7| iag| j8v| mqw| 6ft| db6| ies| tln| v6y| hoy| 6bp| ol7| vnb| x7g| svj| 5hk| eh5| eqk| r5k| qis| 6ip| s6j| nfp| 6mk| aw6| plz| j4i| woj| 4ka| lh5| wqt| u5m| gyb| 5cl| 5bp| sz5| gra| q5f| cux| 4ke| dx4| kgh| z4y| knq| 4jo| ew4| sa4| fca| r5c| pmg| f3f| hya| 3js| qt3| iqo| b3q| scb| 3hg| by4| tl4| dzj| k4r| dku| 2vn| aw2| gcm| l2y| gnt| 3xw| sa3| mxh| c3a| btg| yfw| 1vj| kc1| yub| b22| zrq| h2v| bcl| 2hc| gj2| uoy| o2k| plj| tbw| 1zn|