日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Java nio入門教程詳解(0026)

 360lec 2016-09-30
  3.5.3 SocketChannel
  下面開始學(xué)習(xí)SocketChannel,它是使用最多的socket通道類:
  public abstract class SocketChannel extends AbstractSelectableChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel {
  // 這里僅列出部分API
  public static SocketChannel open() throws IOException
  public static SocketChannel open(InetSocketAddress remote) throws IOException
  public abstract Socket socket();
  public abstract boolean connect (SocketAddress remote) throws IOException;
  public abstract boolean isConnectionPending();
  public abstract boolean finishConnect() throws IOException;
  public abstract boolean isConnected();
  public final int validOps()
  }
  Socket和SocketChannel類封裝點(diǎn)對(duì)點(diǎn)、有序的網(wǎng)絡(luò)連接,類似于我們所熟知并喜愛的TCP/IP網(wǎng)絡(luò)連接。SocketChannel扮演客戶端發(fā)起同一個(gè)監(jiān)聽服務(wù)器的連接。直到連接成功,它才能收到數(shù)據(jù)并且只會(huì)從連接到的地址接收。(對(duì)于 ServerSocketChannel,由于涉及到validOps()方法,我們將在第四章檢查選擇器時(shí)進(jìn)行討論。通用的 read/write 方法也未在此列出,詳情請(qǐng)參考 3.1.2節(jié)。)
  每個(gè)SocketChannel對(duì)象創(chuàng)建時(shí)都是同一個(gè)對(duì)等的java.net.Socket對(duì)象串聯(lián)的。靜態(tài)的open()方法可以創(chuàng)建一個(gè)新的SocketChannel對(duì)象,而在新創(chuàng)建的SocketChannel上調(diào)用socket()方法能返回它對(duì)等的Socket對(duì)象;在該Socket上調(diào)用getChannel()方法則能返回最初的那個(gè)SocketChannel。
  雖然每個(gè)SocketChannel對(duì)象都會(huì)創(chuàng)建一個(gè)對(duì)等的Socket對(duì)象,反過來卻不成立。直接創(chuàng)建的Socket對(duì)象不會(huì)關(guān)聯(lián)SocketChannel對(duì)象,它們的getChannel()方法只返回null。
  新創(chuàng)建的SocketChannel雖已打開卻是未連接的。在一個(gè)未連接的SocketChannel對(duì)象上嘗試一個(gè)I/O操作會(huì)導(dǎo)致NotYetConnectedException異常。我們可以通過在通道上直接調(diào)用connect()方法或在通道關(guān)聯(lián)的Socket對(duì)象上調(diào)用connect()來將該 socket 通道連接。一旦一個(gè) socket 通道被連接,它將保持連接狀態(tài)直到被關(guān)閉。您可以通過調(diào)用布爾型的isConnected()方法來測(cè)試某個(gè)SocketChannel當(dāng)前是否已連接。
  第二種帶InetSocketAddress參數(shù)形式的open()是在返回之前進(jìn)行連接的便捷方法。這段代碼:
  SocketChannel socketChannel = SocketChannel.open (new InetSocketAddress ("somehost", somePort));
  等價(jià)于下面這段代碼:
  SocketChannel socketChannel = SocketChannel.open();
  socketChannel.connect (new InetSocketAddress ("somehost", somePort));
  如果您選擇使用傳統(tǒng)方式進(jìn)行連接——通過在對(duì)等Socket對(duì)象上調(diào)用connect()方法,那么傳統(tǒng)的連接語義將適用于此。線程在連接建立好或超時(shí)過期之前都將保持阻塞。如果您選擇通過在通道上直接調(diào)用connect()方法來建立連接并且通道處于阻塞模式(默認(rèn)模式),那么連接過程實(shí)際上是一樣的。
  在SocketChannel上并沒有一種connect()方法可以讓您指定超時(shí)(timeout)值,當(dāng)connect()方法在非阻塞模式下被調(diào)用時(shí)SocketChannel提供并發(fā)連接:它發(fā)起對(duì)請(qǐng)求地址的連接并且立即返回值。如果返回值是true,說明連接立即建立了(這可能是本地環(huán)回連接);如果連接不能立即建立,connect()方法會(huì)返回false且并發(fā)地繼續(xù)連接建立過程。
  面向流的的socket建立連接狀態(tài)需要一定的時(shí)間,因?yàn)閮蓚€(gè)待連接系統(tǒng)之間必須進(jìn)行包對(duì)話以建立維護(hù)流socket所需的狀態(tài)信息??缭介_放互聯(lián)網(wǎng)連接到遠(yuǎn)程系統(tǒng)會(huì)特別耗時(shí)。假如某個(gè)SocketChannel上當(dāng)前正由一個(gè)并發(fā)連接,isConnectPending()方法就會(huì)返回true值。
  調(diào)用finishConnect()方法來完成連接過程,該方法任何時(shí)候都可以安全地進(jìn)行調(diào)用。假如在一個(gè)非阻塞模式的SocketChannel對(duì)象上調(diào)用finishConnect()方法,將可能出現(xiàn)下列情形之一:
  connect()方法尚未被調(diào)用。那么將產(chǎn)生NoConnectionPendingException異常。
  連接建立過程正在進(jìn)行,尚未完成。那么什么都不會(huì)發(fā)生,finishConnect()方法會(huì)立即返回false值。
  在非阻塞模式下調(diào)用connect()方法之后,SocketChannel又被切換回了阻塞模式。那么如果有必要的話,調(diào)用線程會(huì)阻塞直到連接建立完成,finishConnect()方法接著就會(huì)返回true值。
  在初次調(diào)用connect()或最后一次調(diào)用finishConnect()之后,連接建立過程已經(jīng)完成。那么SocketChannel對(duì)象的內(nèi)部狀態(tài)將被更新到已連接狀態(tài),finishConnect()方法會(huì)返回true值,然后SocketChannel對(duì)象就可以被用來傳輸數(shù)據(jù)了。
  連接已經(jīng)建立。那么什么都不會(huì)發(fā)生,finishConnect()方法會(huì)返回true值。
  當(dāng)通道處于中間的連接等待(connection-pending)狀態(tài)時(shí),您只可以調(diào)用finishConnect()、isConnectPending()或isConnected()方法。一旦連接建立過程成功完成,isConnected()將返回true值。
  InetSocketAddress addr = new InetSocketAddress(host, port);
  SocketChannel sc = SocketChannel.open();
  sc.configureBlocking (false);
  sc.connect (addr);
  while ( !sc.finishConnect()) {
  doSomethingElse();
  }
  doSomethingWithChannel(sc);
  sc.close();
  例 3-8 是一段用來管理異步連接的可用代碼。
  /*
  *例 3-8 建立并發(fā)連接
  */
  package com.ronsoft.books.nio.channels;
  import java.nio.channels.SocketChannel;
  import java.net.InetSocketAddress;
  /**
  * Demonstrate asynchronous connection of a SocketChannel.
  * @author Ron Hitchens (ron@ronsoft.com)
  */
  public class ConnectAsync {
  public static void main (String [] argv) throws Exception {
  String host = "localhost";
  int port = 80;
  if (argv.length == 2) {
  host = argv[0];
  port = Integer.parseInt (argv[1]);
  }
  InetSocketAddress addr = new InetSocketAddress(host, port);
  SocketChannel sc = SocketChannel.open();
  sc.configureBlocking (false);
  System.out.println ("initiating connection");
  sc.connect (addr);
  while ( !sc.finishConnect()) {
  doSomethingUseful();
  }
  System.out.println ("connection established");
  // Do something with the connected socket
  // The SocketChannel is still nonblocking
  sc.close();
  }
  private static void doSomethingUseful() {
  System.out.println ("doing something useless");
  }
  }
  如果嘗試異步連接失敗,那么下次調(diào)用finishConnect()方法會(huì)產(chǎn)生一個(gè)適當(dāng)?shù)慕?jīng)檢查的異常以指出問題的性質(zhì)。通道然后就會(huì)被關(guān)閉并將不能被連接或再次使用。
  與連接相關(guān)的方法使得我們可以對(duì)一個(gè)通道進(jìn)行輪詢并在連接進(jìn)行過程中判斷通道所處的狀態(tài)。第四章中,我們將了解到如何使用選擇器來避免進(jìn)行輪詢并在異步連接建立之后收到通知。
  Socket通道是線程安全的。并發(fā)訪問時(shí)無需特別措施來保護(hù)發(fā)起訪問的多個(gè)線程,不過任何時(shí)候都只有一個(gè)讀操作和一個(gè)寫操作在進(jìn)行中。請(qǐng)記住,sockets 是面向流的而非包導(dǎo)向的。它們可以保證發(fā)送的字節(jié)會(huì)按照順序到達(dá)但無法承諾維持字節(jié)分組。某個(gè)發(fā)送器可能給一個(gè)socket寫入了20 個(gè)字節(jié)而接收器調(diào)用read()方法時(shí)卻只收到了其中的3個(gè)字節(jié)。剩下的17個(gè)字節(jié)還是傳輸中。由于這個(gè)原因,讓多個(gè)不配合的線程共享某個(gè)流 socket 的同一側(cè)絕非一個(gè)好的設(shè)計(jì)選擇。
  connect()和finishConnect()方法是互相同步的,并且只要其中一個(gè)操作正在進(jìn)行,任何讀或?qū)懙姆椒ㄕ{(diào)用都會(huì)阻塞,即使是在非阻塞模式下。如果此情形下您有疑問或不能承受一個(gè)讀或?qū)懖僮髟谀硞€(gè)通道上阻塞,請(qǐng)用isConnected()方法測(cè)試一下連接狀態(tài)。
  Java nio入門教程詳解(二十七)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多