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)頁(yè)
        //創(chuàng)建一個(gè)URL實(shí)例
        URL url=new URL("http://www.baidu.com");
        //通過(guò)openstream方法虎丘資源字節(jié)輸入流
        InputStream is=url.openStream();
         //字節(jié)輸入轉(zhuǎn)為字符,不指定編碼,中文可能亂碼
        InputStreamReader isr=new InputStreamReader(is,"UTF-8"); 
         //字符輸入假如緩存,提高讀寫(xiě)效率
        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ù)器端說(shuō)" + 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)聽(tīng)端口
        ServerSocket serverSocket=new ServerSocket(10086);
        //2.調(diào)用accept 開(kāi)始監(jiān)聽(tīng),等待客戶端連接
        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ù)器,客戶端說(shuō)" + 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. 打開(kāi)連接到Socket的輸入輸出流
    socket.openInputStream()
  3. 按照協(xié)議對(duì)Socket進(jìn)行讀寫(xiě)
    包裝流輸入輸出
  4. 關(guān)閉輸入,輸出流,關(guān)閉socket
    serverSocket還要關(guān)閉socket

2. 阻塞IO

java的I/O接口

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

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

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


NIO

基本原理

  1. 是事件到來(lái)時(shí),才執(zhí)行,不是像BIO那樣始終監(jiān)視
  2. 有線程間通信方式,通過(guò)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í)行并沒(méi)有實(shí)現(xiàn)連接,需要在listen方法中調(diào)用
        //用channel.finisConnection 才能完成連接
        channel.connect(new InetSocketAddress(ip, port));
        //將通道管理器和通道綁定,并為該通道注冊(cè)selecionKey.OP_CONNECT事件
        channel.register(mSelector, SelectionKey.OP_CONNECT);
    }

    /**
     * 采用輪詢的方式監(jiān)聽(tīng)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通道,并對(duì)改通道做一些初始化操作
     */

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


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

    /**
     * 采用輪詢的方式監(jiān)聽(tīng)selector上是否有需要處理的事件
     */
    /**
     * 采用輪詢的方式監(jiān)聽(tīng)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)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挑势,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子螟左,更是在濱河造成了極大的恐慌卢未,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件态蒂,死亡現(xiàn)場(chǎng)離奇詭異杭措,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)钾恢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)手素,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人瘩蚪,你說(shuō)我怎么就攤上這事泉懦。” “怎么了疹瘦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵崩哩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)邓嘹,這世上最難降的妖魔是什么酣栈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮汹押,結(jié)果婚禮上矿筝,老公的妹妹穿的比我還像新娘。我一直安慰自己鲸阻,他們只是感情好跋涣,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著鸟悴,像睡著了一般陈辱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上细诸,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天沛贪,我揣著相機(jī)與錄音,去河邊找鬼震贵。 笑死利赋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的猩系。 我是一名探鬼主播媚送,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼寇甸!你這毒婦竟也來(lái)了塘偎?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拿霉,失蹤者是張志新(化名)和其女友劉穎吟秩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體绽淘,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涵防,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沪铭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壮池。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖伦意,靈堂內(nèi)的尸體忽然破棺而出火窒,到底是詐尸還是另有隱情,我是刑警寧澤驮肉,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站已骇,受9級(jí)特大地震影響离钝,放射性物質(zhì)發(fā)生泄漏票编。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一卵渴、第九天 我趴在偏房一處隱蔽的房頂上張望慧域。 院中可真熱鬧,春花似錦浪读、人聲如沸昔榴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)互订。三九已至,卻和暖如春痘拆,著一層夾襖步出監(jiān)牢的瞬間仰禽,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工纺蛆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吐葵,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓桥氏,卻偏偏與公主長(zhǎng)得像温峭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子字支,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

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