IO

  • java網(wǎng)絡(luò)編程
  • 阻塞IO
  • NIO

1. java網(wǎng)絡(luò)編程

  • 基礎(chǔ)知識(shí)
    1.ip地址和端口號(hào)
    2.tcp/udp協(xié)議
    3.URL
    4.InetAddress
    public void test() throws IOException{
        //使用URL讀取網(wǎng)頁
        //創(chuàng)建一個(gè)URL實(shí)例
        URL url=new URL("http://www.baidu.com");
        //通過openstream方法虎丘資源字節(jié)輸入流
        InputStream is=url.openStream();
         //字節(jié)輸入轉(zhuǎn)為字符,不指定編碼,中文可能亂碼
        InputStreamReader isr=new InputStreamReader(is,"UTF-8"); 
         //字符輸入假如緩存,提高讀寫效率
        BufferedReader br=new BufferedReader(isr);
        String data = br.readLine();
        while (data != null) {
            System.out.println(data);//輸出
            data=br.readLine();
        }
        br.close();
        isr.close();
        is.close();
    }
  • socket
    1.創(chuàng)建socket實(shí)例
    2.客戶端鏈接
    3.服務(wù)端鏈接
    4.總結(jié)

客戶端代碼

    public void socket() throws IOException {
        //1.創(chuàng)建客戶端socket,指定服務(wù)器地址和端口
        Socket socket = new Socket("localhost", 10086);
        //2.獲取輸出流
        OutputStream os = socket.getOutputStream();
        PrintWriter pw = new PrintWriter(os);  //輸出包裝成打印流
        pw.flush();
        socket.shutdownOutput();

        //3.獲取輸入流,讀取服務(wù)器響應(yīng)數(shù)據(jù)
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String info = null;
        if ((info = br.readLine()) != null) {
            System.out.println("我是客戶端,服務(wù)器端說" + info);
        }
        //4.關(guān)閉資源
        br.close();
        is.close();
        pw.close();
        os.close();
        socket.close();
    }

服務(wù)端代碼

    /**
     * 基于TCP協(xié)議的socket通信,實(shí)現(xiàn)用戶登錄,服務(wù)端
     */
    public void  serverSocket() throws IOException{
        //1.創(chuàng)建一個(gè)服務(wù)器端的socket,即ServerSocket,指定綁定端口,監(jiān)聽端口
        ServerSocket serverSocket=new ServerSocket(10086);
        //2.調(diào)用accept 開始監(jiān)聽,等待客戶端連接
        Socket socket=serverSocket.accept();
        //3.獲取輸入流,讀取客戶端
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String info = null;
        if ((info = br.readLine()) != null) {
            System.out.println("我是服務(wù)器,客戶端說" + info);
        }
        socket.shutdownOutput();//關(guān)閉輸入流

        //4.獲取輸出流,響應(yīng)客戶端信息
        OutputStream os = socket.getOutputStream();
        PrintWriter pw = new PrintWriter(os);  //輸出包裝成打印流
        pw.write("歡迎您......");
        pw.flush();

        //5.關(guān)閉資源
        pw.close();
        os.close();
        br.close();
        is.close();
        socket.close();
        serverSocket.close();

    }
總結(jié)
  1. 創(chuàng)建ServerSocket和Socket
    serverSocket.accept()
  2. 打開連接到Socket的輸入輸出流
    socket.openInputStream()
  3. 按照協(xié)議對Socket進(jìn)行讀寫
    包裝流輸入輸出
  4. 關(guān)閉輸入,輸出流,關(guān)閉socket
    serverSocket還要關(guān)閉socket

2. 阻塞IO

java的I/O接口

  1. 基于字節(jié)
    InputStream或OutputStream
  2. 基于字符
    Writer和Reader
  3. 基于磁盤
    File
  4. 基于網(wǎng)絡(luò)
    Socket

一直是阻塞的,會(huì)等到數(shù)據(jù)到來時(shí)才返回
eg:serverSocket.accept()一直等到有客戶端socket連接時(shí)啟用一個(gè)線程

總結(jié)
1.BIO數(shù)據(jù)在寫入OutputStream或者從InputStream讀取時(shí)都有阻塞
2.當(dāng)前一些需要大量HTTP長連接


NIO

基本原理

  1. 是事件到來時(shí),才執(zhí)行,不是像BIO那樣始終監(jiān)視
  2. 有線程間通信方式,通過wait/notify方法,保證每次上下文切換都是有意義的,提高CPU的效率
  3. 有一個(gè)線程處理所有的IO事件

通信模型
雙向通道

代碼

客戶端

    public Selector mSelector;

    public void initClient(String ip, int port) throws IOException {
        //1.獲取一個(gè)Socket通道
        SocketChannel channel = SocketChannel.open();
        //2.設(shè)置通道為非阻塞
        channel.configureBlocking(false);
        //3.獲得一個(gè)通道管理器
        mSelector = Selector.open();

        //客戶端連接服務(wù)器,方法執(zhí)行并沒有實(shí)現(xiàn)連接,需要在listen方法中調(diào)用
        //用channel.finisConnection 才能完成連接
        channel.connect(new InetSocketAddress(ip, port));
        //將通道管理器和通道綁定,并為該通道注冊selecionKey.OP_CONNECT事件
        channel.register(mSelector, SelectionKey.OP_CONNECT);
    }

    /**
     * 采用輪詢的方式監(jiān)聽selector上是否有需要處理的事件,有則進(jìn)行處理
     */
    public void listen() throws IOException {
        //輪詢方式
        while (true) {
            mSelector.select();
            //獲得selector中選中的迭代器
            Iterator iterator = mSelector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = (SelectionKey) iterator.next();
                //刪除已選的key   防止重復(fù)
                iterator.remove();
                //連接事件發(fā)生
                if (key.isConnectable()) {
                    SocketChannel channel= (SocketChannel) key.channel();
                    //如果正在連接,則完成連接
                    if (channel.isConnectionPending()) {
                        channel.finishConnect();
                    }

                    //設(shè)置成非阻塞
                    channel.configureBlocking(false);

                    //在這里可以給服務(wù)器發(fā)送消息
                    channel.write(ByteBuffer.wrap(
                                         new String("向服務(wù)器發(fā)送數(shù)據(jù)").getBytes()));

                    //和服務(wù)端連接成功后,為了接收服務(wù)器消息,需要設(shè)置讀的權(quán)限
                    channel.register(mSelector,SelectionKey.OP_READ);
                    //
                    //獲得可讀事件
                }else if(key.isReadable()){
                    read(key);
                }
            }
        }
    }

    private void read(SelectionKey key) {

    }

服務(wù)器端

 //通道管理器
    private Selector mSelector;

    /**
     * 獲得一個(gè)ServerSocket通道,并對改通道做一些初始化操作
     */

    public void initServer(int port) throws IOException{
        //獲得一個(gè)ServerSocket通道
        ServerSocketChannel channel=ServerSocketChannel.open();
        //2.設(shè)置通道為非阻塞
        channel.configureBlocking(false);
        //將通道對應(yīng)的serverSocket綁定到port端口
        channel.socket().bind(new InetSocketAddress(port));
        //3.獲得一個(gè)通道管理器
        mSelector = Selector.open();


        //將通道管理器和通道綁定,并為該通道注冊selecionKey.OP_ACCEPT事件
        //注冊該時(shí)間后,當(dāng)事件到達(dá)時(shí),selector.select會(huì)反悔,
        //如果該事件沒到達(dá)selector.select會(huì)一直阻塞
        channel.register(mSelector, SelectionKey.OP_ACCEPT);
    }

    /**
     * 采用輪詢的方式監(jiān)聽selector上是否有需要處理的事件
     */
    /**
     * 采用輪詢的方式監(jiān)聽selector上是否有需要處理的事件,有則進(jìn)行處理
     */
    public void listen() throws IOException {
        System.out.println("服務(wù)器端啟動(dòng)成功");
        //輪詢方式
        while (true) {
            mSelector.select();
            //獲得selector中選中的迭代器
            Iterator iterator = mSelector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = (SelectionKey) iterator.next();
                //刪除已選的key   防止重復(fù)
                iterator.remove();
                //連接事件發(fā)生
                if (key.isConnectable()) {
                    SocketChannel channel= (SocketChannel) key.channel();
                    //如果正在連接,則完成連接
                    if (channel.isConnectionPending()) {
                        channel.finishConnect();
                    }

                    //設(shè)置成非阻塞
                    channel.configureBlocking(false);

                    //在這里可以給服務(wù)器發(fā)送消息
                    channel.write(ByteBuffer.wrap(
                                            new String("向服務(wù)器發(fā)送數(shù)據(jù)").getBytes()));

                    //和服務(wù)端連接成功后,為了接收服務(wù)器消息,需要設(shè)置讀的權(quán)限
                    channel.register(mSelector,SelectionKey.OP_READ);
                    //
                    //獲得可讀事件
                }else if(key.isReadable()){
                    read(key);
                }
            }
        }
    }

    private void read(SelectionKey key) {

    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概述 NIO主要有三大核心部分:Channel(通道),Buffer(緩沖區(qū)),Selector。 傳統(tǒng)IO基于...
    時(shí)之令閱讀 4,082評論 0 8
  • 由于最近在看Netty框架相關(guān)的東西,就把Java IO 這塊的內(nèi)容全部重新復(fù)習(xí)了一遍。這篇文章主要是把我在復(fù)習(xí)過...
    大大大浣熊閱讀 1,039評論 3 1
  • nio 同步: 自己親自出馬持銀行卡到銀行取錢(使用同步IO時(shí),Java自己處理IO讀寫)。 異步: 委托一小弟拿...
    CatherYan閱讀 1,149評論 1 12
  • 概述 流是一組有順序的,有起點(diǎn)和終點(diǎn)的字節(jié)集合,是對數(shù)據(jù)傳輸?shù)目偡Q或抽象。即數(shù)據(jù)在兩設(shè)備間的傳輸稱為流,流的本質(zhì)是...
    wustor閱讀 1,885評論 5 6
  • 通常的IO操作,只要不是操作系統(tǒng)內(nèi)存的數(shù)據(jù),基本都是IO操作,常見的IO操作,一般都是 操作磁盤、網(wǎng)卡這些(串口這...
    軒居晨風(fēng)閱讀 812評論 0 1

友情鏈接更多精彩內(nèi)容