IO

  • java网络编程
  • 阻塞IO
  • NIO

1. java网络编程

  • 基础知识
    1.ip地址和端口号
    2.tcp/udp协议
    3.URL
    4.InetAddress
    public void test() throws IOException{
        //使用URL读取网页
        //创建一个URL实例
        URL url=new URL("http://www.baidu.com");
        //通过openstream方法虎丘资源字节输入流
        InputStream is=url.openStream();
         //字节输入转为字符,不指定编码,中文可能乱码
        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.创建socket实例
    2.客户端链接
    3.服务端链接
    4.总结

客户端代码

    public void socket() throws IOException {
        //1.创建客户端socket,指定服务器地址和端口
        Socket socket = new Socket("localhost", 10086);
        //2.获取输出流
        OutputStream os = socket.getOutputStream();
        PrintWriter pw = new PrintWriter(os);  //输出包装成打印流
        pw.flush();
        socket.shutdownOutput();

        //3.获取输入流,读取服务器响应数据
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String info = null;
        if ((info = br.readLine()) != null) {
            System.out.println("我是客户端,服务器端说" + info);
        }
        //4.关闭资源
        br.close();
        is.close();
        pw.close();
        os.close();
        socket.close();
    }

服务端代码

    /**
     * 基于TCP协议的socket通信,实现用户登录,服务端
     */
    public void  serverSocket() throws IOException{
        //1.创建一个服务器端的socket,即ServerSocket,指定绑定端口,监听端口
        ServerSocket serverSocket=new ServerSocket(10086);
        //2.调用accept 开始监听,等待客户端连接
        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("我是服务器,客户端说" + info);
        }
        socket.shutdownOutput();//关闭输入流

        //4.获取输出流,响应客户端信息
        OutputStream os = socket.getOutputStream();
        PrintWriter pw = new PrintWriter(os);  //输出包装成打印流
        pw.write("欢迎您......");
        pw.flush();

        //5.关闭资源
        pw.close();
        os.close();
        br.close();
        is.close();
        socket.close();
        serverSocket.close();

    }
总结
  1. 创建ServerSocket和Socket
    serverSocket.accept()
  2. 打开连接到Socket的输入输出流
    socket.openInputStream()
  3. 按照协议对Socket进行读写
    包装流输入输出
  4. 关闭输入,输出流,关闭socket
    serverSocket还要关闭socket

2. 阻塞IO

java的I/O接口

  1. 基于字节
    InputStream或OutputStream
  2. 基于字符
    Writer和Reader
  3. 基于磁盘
    File
  4. 基于网络
    Socket

一直是阻塞的,会等到数据到来时才返回
eg:serverSocket.accept()一直等到有客户端socket连接时启用一个线程

总结
1.BIO数据在写入OutputStream或者从InputStream读取时都有阻塞
2.当前一些需要大量HTTP长连接


NIO

基本原理

  1. 是事件到来时,才执行,不是像BIO那样始终监视
  2. 有线程间通信方式,通过wait/notify方法,保证每次上下文切换都是有意义的,提高CPU的效率
  3. 有一个线程处理所有的IO事件

通信模型
双向通道

代码

客户端

    public Selector mSelector;

    public void initClient(String ip, int port) throws IOException {
        //1.获取一个Socket通道
        SocketChannel channel = SocketChannel.open();
        //2.设置通道为非阻塞
        channel.configureBlocking(false);
        //3.获得一个通道管理器
        mSelector = Selector.open();

        //客户端连接服务器,方法执行并没有实现连接,需要在listen方法中调用
        //用channel.finisConnection 才能完成连接
        channel.connect(new InetSocketAddress(ip, port));
        //将通道管理器和通道绑定,并为该通道注册selecionKey.OP_CONNECT事件
        channel.register(mSelector, SelectionKey.OP_CONNECT);
    }

    /**
     * 采用轮询的方式监听selector上是否有需要处理的事件,有则进行处理
     */
    public void listen() throws IOException {
        //轮询方式
        while (true) {
            mSelector.select();
            //获得selector中选中的迭代器
            Iterator iterator = mSelector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = (SelectionKey) iterator.next();
                //删除已选的key   防止重复
                iterator.remove();
                //连接事件发生
                if (key.isConnectable()) {
                    SocketChannel channel= (SocketChannel) key.channel();
                    //如果正在连接,则完成连接
                    if (channel.isConnectionPending()) {
                        channel.finishConnect();
                    }

                    //设置成非阻塞
                    channel.configureBlocking(false);

                    //在这里可以给服务器发送消息
                    channel.write(ByteBuffer.wrap(
                                         new String("向服务器发送数据").getBytes()));

                    //和服务端连接成功后,为了接收服务器消息,需要设置读的权限
                    channel.register(mSelector,SelectionKey.OP_READ);
                    //
                    //获得可读事件
                }else if(key.isReadable()){
                    read(key);
                }
            }
        }
    }

    private void read(SelectionKey key) {

    }

服务器端

 //通道管理器
    private Selector mSelector;

    /**
     * 获得一个ServerSocket通道,并对改通道做一些初始化操作
     */

    public void initServer(int port) throws IOException{
        //获得一个ServerSocket通道
        ServerSocketChannel channel=ServerSocketChannel.open();
        //2.设置通道为非阻塞
        channel.configureBlocking(false);
        //将通道对应的serverSocket绑定到port端口
        channel.socket().bind(new InetSocketAddress(port));
        //3.获得一个通道管理器
        mSelector = Selector.open();


        //将通道管理器和通道绑定,并为该通道注册selecionKey.OP_ACCEPT事件
        //注册该时间后,当事件到达时,selector.select会反悔,
        //如果该事件没到达selector.select会一直阻塞
        channel.register(mSelector, SelectionKey.OP_ACCEPT);
    }

    /**
     * 采用轮询的方式监听selector上是否有需要处理的事件
     */
    /**
     * 采用轮询的方式监听selector上是否有需要处理的事件,有则进行处理
     */
    public void listen() throws IOException {
        System.out.println("服务器端启动成功");
        //轮询方式
        while (true) {
            mSelector.select();
            //获得selector中选中的迭代器
            Iterator iterator = mSelector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = (SelectionKey) iterator.next();
                //删除已选的key   防止重复
                iterator.remove();
                //连接事件发生
                if (key.isConnectable()) {
                    SocketChannel channel= (SocketChannel) key.channel();
                    //如果正在连接,则完成连接
                    if (channel.isConnectionPending()) {
                        channel.finishConnect();
                    }

                    //设置成非阻塞
                    channel.configureBlocking(false);

                    //在这里可以给服务器发送消息
                    channel.write(ByteBuffer.wrap(
                                            new String("向服务器发送数据").getBytes()));

                    //和服务端连接成功后,为了接收服务器消息,需要设置读的权限
                    channel.register(mSelector,SelectionKey.OP_READ);
                    //
                    //获得可读事件
                }else if(key.isReadable()){
                    read(key);
                }
            }
        }
    }

    private void read(SelectionKey key) {

    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • 概述 NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区),Selector。 传统IO基于...
    时之令阅读 3,677评论 0 8
  • 由于最近在看Netty框架相关的东西,就把Java IO 这块的内容全部重新复习了一遍。这篇文章主要是把我在复习过...
    大大大浣熊阅读 941评论 3 1
  • nio 同步: 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写)。 异步: 委托一小弟拿...
    CatherYan阅读 1,110评论 1 12
  • 概述 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是...
    wustor阅读 1,784评论 5 6
  • 通常的IO操作,只要不是操作系统内存的数据,基本都是IO操作,常见的IO操作,一般都是 操作磁盘、网卡这些(串口这...
    轩居晨风阅读 723评论 0 1