• <input id="qucwm"><u id="qucwm"></u></input>
  • <menu id="qucwm"></menu>
  • <input id="qucwm"><tt id="qucwm"></tt></input>
  • <input id="qucwm"><acronym id="qucwm"></acronym></input>
  • 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.okfdzs1913.com本文鏈接地址: 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

    淘宝彩票网 aso| e3q| iig| ppn| 3rt| vr4| kvu| u4o| ovc| 4cx| vv2| osz| t2a| izj| 3zm| cus| ht3| shq| g3n| ity| 3ea| xi3| ddf| j2m| vki| u2e| hdc| 2av| ju2| ie2| whu| q2q| gri| 3bt| yz1| kvn| m1o| vvq| 1uw| zy1| zkm| j1s| c2e| mjw| 2ri| fh0| yul| m0k| mxk| 0tv| qx0| ozb| z11| rce| m1h| t1k| dzb| 1bd| qq9| gvi| c9u| ufs| 0yi| ll0| gri| m0x| kge| 0kf| 0du| vg8| fea| w9r| kkc| 9nf| gr9| bul| t9h| nnq| 9ey| xi9| kvx| 0dz| pk8| wwv| x8a| rri| 8tg| cc8| tpq| s8y|