乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Java nio入門(mén)教程詳解(0026)

       360lec 2016-09-30
        3.5.3 SocketChannel
        下面開(kāi)始學(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ò)連接,類似于我們所熟知并喜愛(ài)的TCP/IP網(wǎng)絡(luò)連接。SocketChannel扮演客戶端發(fā)起同一個(gè)監(jiān)聽(tīng)服務(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ì)象,反過(guò)來(lái)卻不成立。直接創(chuàng)建的Socket對(duì)象不會(huì)關(guān)聯(lián)SocketChannel對(duì)象,它們的getChannel()方法只返回null。
        新創(chuàng)建的SocketChannel雖已打開(kāi)卻是未連接的。在一個(gè)未連接的SocketChannel對(duì)象上嘗試一個(gè)I/O操作會(huì)導(dǎo)致NotYetConnectedException異常。我們可以通過(guò)在通道上直接調(diào)用connect()方法或在通道關(guān)聯(lián)的Socket對(duì)象上調(diào)用connect()來(lái)將該 socket 通道連接。一旦一個(gè) socket 通道被連接,它將保持連接狀態(tài)直到被關(guān)閉。您可以通過(guò)調(diào)用布爾型的isConnected()方法來(lái)測(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)行連接——通過(guò)在對(duì)等Socket對(duì)象上調(diào)用connect()方法,那么傳統(tǒng)的連接語(yǔ)義將適用于此。線程在連接建立好或超時(shí)過(guò)期之前都將保持阻塞。如果您選擇通過(guò)在通道上直接調(diào)用connect()方法來(lái)建立連接并且通道處于阻塞模式(默認(rèn)模式),那么連接過(guò)程實(shí)際上是一樣的。
        在SocketChannel上并沒(méi)有一種connect()方法可以讓您指定超時(shí)(timeout)值,當(dāng)connect()方法在非阻塞模式下被調(diào)用時(shí)SocketChannel提供并發(fā)連接:它發(fā)起對(duì)請(qǐng)求地址的連接并且立即返回值。如果返回值是true,說(shuō)明連接立即建立了(這可能是本地環(huán)回連接);如果連接不能立即建立,connect()方法會(huì)返回false且并發(fā)地繼續(xù)連接建立過(guò)程。
        面向流的的socket建立連接狀態(tài)需要一定的時(shí)間,因?yàn)閮蓚€(gè)待連接系統(tǒng)之間必須進(jìn)行包對(duì)話以建立維護(hù)流socket所需的狀態(tài)信息。跨越開(kāi)放互聯(lián)網(wǎng)連接到遠(yuǎn)程系統(tǒng)會(huì)特別耗時(shí)。假如某個(gè)SocketChannel上當(dāng)前正由一個(gè)并發(fā)連接,isConnectPending()方法就會(huì)返回true值。
        調(diào)用finishConnect()方法來(lái)完成連接過(guò)程,該方法任何時(shí)候都可以安全地進(jìn)行調(diào)用。假如在一個(gè)非阻塞模式的SocketChannel對(duì)象上調(diào)用finishConnect()方法,將可能出現(xiàn)下列情形之一:
        connect()方法尚未被調(diào)用。那么將產(chǎn)生NoConnectionPendingException異常。
        連接建立過(guò)程正在進(jìn)行,尚未完成。那么什么都不會(huì)發(fā)生,finishConnect()方法會(huì)立即返回false值。
        在非阻塞模式下調(diào)用connect()方法之后,SocketChannel又被切換回了阻塞模式。那么如果有必要的話,調(diào)用線程會(huì)阻塞直到連接建立完成,finishConnect()方法接著就會(huì)返回true值。
        在初次調(diào)用connect()或最后一次調(diào)用finishConnect()之后,連接建立過(guò)程已經(jīng)完成。那么SocketChannel對(duì)象的內(nèi)部狀態(tài)將被更新到已連接狀態(tài),finishConnect()方法會(huì)返回true值,然后SocketChannel對(duì)象就可以被用來(lái)傳輸數(shù)據(jù)了。
        連接已經(jīng)建立。那么什么都不會(huì)發(fā)生,finishConnect()方法會(huì)返回true值。
        當(dāng)通道處于中間的連接等待(connection-pending)狀態(tài)時(shí),您只可以調(diào)用finishConnect()、isConnectPending()或isConnected()方法。一旦連接建立過(guò)程成功完成,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 是一段用來(lái)管理異步連接的可用代碼。
        /*
        *例 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)檢查的異常以指出問(wèn)題的性質(zhì)。通道然后就會(huì)被關(guān)閉并將不能被連接或再次使用。
        與連接相關(guān)的方法使得我們可以對(duì)一個(gè)通道進(jìn)行輪詢并在連接進(jìn)行過(guò)程中判斷通道所處的狀態(tài)。第四章中,我們將了解到如何使用選擇器來(lái)避免進(jìn)行輪詢并在異步連接建立之后收到通知。
        Socket通道是線程安全的。并發(fā)訪問(wèn)時(shí)無(wú)需特別措施來(lái)保護(hù)發(fā)起訪問(wèn)的多個(gè)線程,不過(guò)任何時(shí)候都只有一個(gè)讀操作和一個(gè)寫(xiě)操作在進(jìn)行中。請(qǐng)記住,sockets 是面向流的而非包導(dǎo)向的。它們可以保證發(fā)送的字節(jié)會(huì)按照順序到達(dá)但無(wú)法承諾維持字節(jié)分組。某個(gè)發(fā)送器可能給一個(gè)socket寫(xiě)入了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ì)阻塞,即使是在非阻塞模式下。如果此情形下您有疑問(wèn)或不能承受一個(gè)讀或?qū)懖僮髟谀硞€(gè)通道上阻塞,請(qǐng)用isConnected()方法測(cè)試一下連接狀態(tài)。
        Java nio入門(mén)教程詳解(二十七)

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(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)論公約

        類似文章 更多