javaNIO实战6----> java NIO的阻塞式网络编程

1、在没有NIO的套件的时候,我们都是使用Socket来进行网络编程

      案例如下:

          1.1、服务端实现:

    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try {
            //1、构建一个SocketServer 监听端口8080,这就表示一个进程,当前线程就是main线程,也可以叫IO线程。
            serverSocket = new ServerSocket(8080);
            
            /*
            2、IO线程进行accept,accept的含义就是等待客户端连接的时候,当前IO线程会进行接受,在没有客户端进行连接
               的时候,IO线程就会一直处于阻塞状态,知道有客户端连接后进行处理。有客户端连接后就会返回一个Socket
               实例,用于表示客户端的连接信息。
             */
            Socket socket = serverSocket.accept();

            //3、获取连接的客户端的输入流。
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            
            //4、读取客户端输入流中的消息数据
            String message = bufferedReader.readLine();
            System.out.println("收到客户端消息:" + message);

            //5、获取客户端连接的输出流,用于向客户端输出数据。
            OutputStream outputStream = socket.getOutputStream();
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            bufferedWriter.write("回复客户端消息:回复客户端。\n");
            bufferedWriter.flush();
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

        1.2、客户端实现:

    public static void main(String[] args) {
        try {
            
            //1、构建一个套接字,连接上服务端
            Socket socket = new Socket("127.0.0.1",8080);

            //2、获取当前客户端连接的输出流,用于向服务端输出数据
            OutputStream outputStream = socket.getOutputStream();
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            //记得结尾添加一个换行符 表示结束。
            bufferedWriter.write("你好,我是客户端1!\n");
            bufferedWriter.flush();

            //3、获取当前客户端连接的输入流,用于接收服务端的回复数据
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String message = bufferedReader.readLine();
            System.out.println(message);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

           以上的服务端都是阻塞的,也就是说,我们上面的实现,IO线程会一直阻塞,知道数据准备OK后才会进入到runing过程。

 

2、NIO中的阻塞式网络编程

      2.1、NIO中阻塞式服务端实现

@Test
    public void nioBlockingServer() throws IOException {

        //1、打开一个网络通道,也就是会创建一个进程,当前的线程就是main线程,也可以叫IO线程
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        //2、绑定当前的进程监听的端口为9898
        serverSocketChannel.bind(new InetSocketAddress(9898));

        /*
        3、同样IO线程进行accept,accept的含义就是等待客户端连接的时候,当前IO线程会进行接受,在没有客户端进行连接
           的时候,IO线程就会一直处于阻塞状态,知道有客户端连接后进行处理。有客户端连接后就会返回一个Socket实例,
           用于表示客户端的连接信息。
         */
        SocketChannel socketChannel = serverSocketChannel.accept();

        //3、分配一个缓冲区,用于存储数据。
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        
        //4、读取连接过来的客户端中发送的数据,然后进行打印输出。
        while (socketChannel.read(buffer) != -1) {
            buffer.flip();
            System.out.println(Thread.currentThread().getName() + " : " + new String(buffer.array()));
            buffer.clear();
        }

        //5、回复客户端。
        buffer.put("服务端收到你的回复了".getBytes());
        buffer.flip();
        socketChannel.write(buffer);
        socketChannel.close();
    }

      2.2、NIO中阻塞式客户端实现

    @Test
    public void nioBlockingClient1() throws IOException {
        //1、构建一个套接字连接到服务端,返回一个socket通道。
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
        
        //2、分配一个缓冲区,且想缓冲区中存入消息。
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put("你好我是客户端1!".getBytes());
        buffer.flip();
        
        //3、发送消息到服务端。
        socketChannel.write(buffer);

        //4、告诉服务端发送结束。在非NIO的系统中,是使用换行符来表示发送消息结束的。
        socketChannel.shutdownOutput();
        buffer.clear();
        
        //5、读取服务端的回复消息进行进行输出。
        while (socketChannel.read(buffer) != -1) {
            buffer.flip();
            System.out.println(new String(buffer.array()));
            buffer.clear();
        }
    }

 

3、阻塞式的利弊分析

      3.1、上面的案例中,都是阻塞式的IO网络编程实现。只要服务端启动,就会创建一个进程,监听端口,这个启动的main线程就可以理解为IO线程。如果没有客户端连接,那么就会一直阻塞在accept()方法的地方,一旦有客户端连接过来就会建立好连接并返回一个Socket 或SocketChannel实例,这个实例就包含了客户端的连接信息,可以使用此实例进行客户端发送的数据读取,以及向客户端回复数据。

      3.2、使用多线程来处理多个客户端的连接以及回复,在我们的案例中只有一个客户端会连接成功,因为输出以后IO线程就被结束掉了,因此人们就想出了,使用多线程来同时处理多个客户端的请求,但是每条线程还是阻塞的。

      3.3、阻塞式的这种网模型会严重影响CPU的利用率,性能很差。因此随着计算机的发展,有了非阻塞式的IO,下一遍文章做详细分析。

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值