设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 重新 试卷 创业者
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

BIO和NIO了解多少呢?一起从实践角度重新理解下吧(2)

发布时间:2019-10-23 18:24 所属栏目:21 来源:追逐仰望星空
导读:完成了服务端的设计后,我们来实现一个客户端,首先实例化Socket对象,并且绑定ip为127.0.0.1(本机),端口号为8080,调用write方法向服务器发送数据。 2.5 运行结果 当我们启动服务器,但客户端还没有向服务器发起

完成了服务端的设计后,我们来实现一个客户端,首先实例化Socket对象,并且绑定ip为127.0.0.1(本机),端口号为8080,调用write方法向服务器发送数据。

BIO和NIO了解多少呢?一起从实践角度重新理解下吧

2.5 运行结果

当我们启动服务器,但客户端还没有向服务器发起连接时,控制台结果如下:

BIO和NIO了解多少呢?一起从实践角度重新理解下吧

当客户端启动并向服务器发送数据后,控制台结果如下:

BIO和NIO了解多少呢?一起从实践角度重新理解下吧

2.6 结论

从上面的运行结果,首先我们至少可以看到,在服务器启动后,客户端还没有连接服务器时,服务器由于调用了accept方法,将一直阻塞,直到有客户端请求连接服务器。

03 对客户端功能进行扩展

在上文中,我们实现的客户端的逻辑主要是,建立Socket --> 连接服务器 --> 发送数据,我们的数据是在连接服务器之后就立即发送的,现在我们来对客户端进行一次扩展,当我们连接服务器后,不立即发送数据,而是等待控制台手动输入数据后,再发送给服务端。(服务端代码保持不变)

3.1 代码

  1. public class Consumer { 
  2.     public static void main(String[] args) { 
  3.         try { 
  4.             Socket socket = new Socket("127.0.0.1",8080); 
  5.             String message = null; 
  6.             Scanner sc = new Scanner(System.in); 
  7.             message = sc.next(); 
  8.             socket.getOutputStream().write(message.getBytes()); 
  9.             socket.close(); 
  10.             sc.close(); 
  11.         } catch (IOException e) { 
  12.             // TODO Auto-generated catch block 
  13.             e.printStackTrace(); 
  14.         } 
  15.     } 

3.2 测试

当服务端启动,客户端还没有请求连接服务器时,控制台结果如下:

BIO和NIO了解多少呢?一起从实践角度重新理解下吧

当服务端启动,客户端连接服务端,但没有发送数据时,控制台结果如下:

BIO和NIO了解多少呢?一起从实践角度重新理解下吧

当服务端启动,客户端连接服务端,并且发送数据时,控制台结果如下:

BIO和NIO了解多少呢?一起从实践角度重新理解下吧

3.3 结论

从上文的运行结果中我们可以看到,服务器端在启动后,首先需要等待客户端的连接请求(第一次阻塞),如果没有客户端连接,服务端将一直阻塞等待,然后当客户端连接后,服务器会等待客户端发送数据(第二次阻塞),如果客户端没有发送数据,那么服务端将会一直阻塞等待客户端发送数据。服务端从启动到收到客户端数据的这个过程,将会有两次阻塞的过程。这就是BIO的非常重要的一个特点,BIO会产生两次阻塞,第一次在等待连接时阻塞,第二次在等待数据时阻塞。

04 BIO

4.1 在单线程条件下BIO的弱点

在上文中,我们实现了一个简易的服务器,这个简易的服务器是以单线程运行的,其实我们不难看出,当我们的服务器接收到一个连接后,并且没有接收到客户端发送的数据时,是会阻塞在read()方法中的,那么此时如果再来一个客户端的请求,服务端是无法进行响应的。换言之,在不考虑多线程的情况下,BIO是无法处理多个客户端请求的。

4.2 BIO如何处理并发

在刚才的服务器实现中,我们实现的是单线程版的BIO服务器,不难看出,单线程版的BIO并不能处理多个客户端的请求,那么如何能使BIO处理多个客户端请求呢。

其实不难想到,我们只需要在每一个连接请求到来时,创建一个线程去执行这个连接请求,就可以在BIO中处理多个客户端请求了,这也就是为什么BIO的其中一条概念是服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理。

4.3 多线程BIO服务器简易实现

  1. public class Server { 
  2.     public static void main(String[] args) { 
  3.         byte[] buffer = new byte[1024]; 
  4.         try { 
  5.             ServerSocket serverSocket = new ServerSocket(8080); 
  6.             System.out.println("服务器已启动并监听8080端口"); 
  7.             while (true) { 
  8.                 System.out.println(); 
  9.                 System.out.println("服务器正在等待连接..."); 
  10.                 Socket socket = serverSocket.accept(); 
  11.                 new Thread(new Runnable() { 
  12.                     @Override 
  13.                     public void run() { 
  14.                         System.out.println("服务器已接收到连接请求..."); 
  15.                         System.out.println(); 
  16.                         System.out.println("服务器正在等待数据..."); 
  17.                         try { 
  18.                             socket.getInputStream().read(buffer); 
  19.                         } catch (IOException e) { 
  20.                             // TODO Auto-generated catch block 
  21.                             e.printStackTrace(); 
  22.                         } 
  23.                         System.out.println("服务器已经接收到数据"); 
  24.                         System.out.println(); 
  25.                         String content = new String(buffer); 
  26.                         System.out.println("接收到的数据:" + content); 
  27.                     } 
  28.                 }).start(); 
  29.                  
  30.             } 
  31.         } catch (IOException e) { 
  32.             // TODO Auto-generated catch block 
  33.             e.printStackTrace(); 
  34.         } 
  35.     } 

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读