Java网络编程----通过实现简易聊天工具来聊聊BIO

科技资讯 投稿 13100 0 评论

Java网络编程----通过实现简易聊天工具来聊聊BIO

BIO即阻塞式IO,Blocking IO
blocking [ˈblɒkɪŋ]
v. 堵塞; 阻塞; 堵住(某人的路等; 挡住(某人的视线等; 妨碍; 阻碍;
那究竟什么是阻塞呢?
这里的阻塞和多线程并发控制中,对未持有锁的线程进行同步阻塞是两个概念。更多的是指停滞不前,由于未接受到指令,只能继续等待的意思。

西餐厅中,有1个服务员负责招待。客人进入餐厅中,服务员会根据客人的需要下单或上菜。
当客人A要求点菜时,服务员A开始下单。在这个过程中,客人中间发生了停顿,或者犹豫不决时,服务员只能阻塞等待,不能直接停滞,忙其他的事情。这就是所谓的阻塞。
这样就会有一个问题,服务员只能做完一件事,再做一件事,当有客人B也有要求时,则不能并发执行,这里就是前文中说的多线程同步。

1、服务员等待指令,只能原地等候下一个指令。
2、由于服务员数量有限,即使其他客人有指令需要下发,服务员依然无法执行。
blocking 属于前者,即服务员只能等待当前客人继续发送指令。
后者则属于多线程同步问题,由于服务员数量有限,无法并发执行事务。
针对于后者,我们一般通过多线程来解决,而前者才是我们今天聊的重点。
大概明白了什么是blocking阻塞之后,我们来看个由blocking IO实现的聊天工具:

 1 package com.example.demo.learn.tcp;
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.io.OutputStream;
 6 import java.net.ServerSocket;
 7 import java.net.Socket;
 8 import java.util.Scanner;
 9 
10 /**
11  * @discription
12  */
13 
14 public class TCPServer {
15     public static void main(String[] args throws IOException {
16         ServerSocket serverSocket = new ServerSocket(9999;
17         while (true {
18             Socket acceptSocket = serverSocket.accept(;//注意这里
19             ChatThread chatThread = new ChatThread(acceptSocket;
20             new Thread(chatThread.start(;
21         }
22     }
23 }
24 
25 class ChatThread implements Runnable {
26     private Socket clientSocket;
27 
28     ChatThread(Socket clientSocket {
29         this.clientSocket = clientSocket;
30     }
31 
32     @Override
33     public void run( {
34         try {
35 
36             OutputStream os = clientSocket.getOutputStream(;
37             SayThread sayThread = new SayThread(os;
38             new Thread(sayThread.start(;
39 
40             InputStream is = clientSocket.getInputStream(;
41             byte[] buffer = new byte[1024];
42             int len = is.read(buffer;//注意这里
43             while (len > 0 {
44                 String msg = new String(buffer, 0, len;
45                 System.out.println("";
46                 System.out.println("receive client msg:";
47                 System.out.println(msg;
48                 System.out.println("";
49                 len = is.read(buffer;//注意这里
50             }
51             clientSocket.close(;
52 
53         } catch (Exception ex {
54             //logs
55         }
56 
57     }
58 }
59 
60 class SayThread implements Runnable {
61     private OutputStream os;
62 
63     SayThread(OutputStream outputStream {
64         this.os = outputStream;
65     }
66 
67     @Override
68     public void run( {
69         try {
70             os.write("server connect success!!!".getBytes(;
71             Scanner inputScanner = new Scanner(System.in;
72             while (true {
73                 String str = inputScanner.nextLine(;
74                 os.write(str.getBytes(;
75                 os.flush(;
76             }
77 
78         } catch (Exception ex {
79             //logs
80         }
81 
82     }
83 }

Client端代码:

1 package com.zzzlei.zxxb.experience; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.io.OutputStream; 6 import java.net.Socket; 7 import java.util.Scanner; 8 9 /** 10 * @discription 11 */ 12 public class TCPClient { 13 public static void main(String[] args throws IOException { 14 Socket clientSocket=new Socket("127.0.0.1",9999; 15 ChatThread chatThread = new ChatThread(clientSocket; 16 new Thread(chatThread.start(; 17 18 } 19 } 20 21 class ChatThread implements Runnable { 22 private Socket clientSocket; 23 24 ChatThread(Socket clientSocket { 25 this.clientSocket = clientSocket; 26 } 27 28 @Override 29 public void run( { 30 try { 31 OutputStream os = clientSocket.getOutputStream(; 32 SayThread sayThread = new SayThread(os; 33 new Thread(sayThread.start(; 34 35 InputStream is = clientSocket.getInputStream(; 36 byte[] buffer = new byte[1024]; 37 int len = is.read(buffer;//注意这里 38 while (len > 0 { 39 String msg = new String(buffer, 0, len; 40 System.out.println(""; 41 System.out.println("receive server msg :"; 42 System.out.println(msg; 43 System.out.println(""; 44 len = is.read(buffer;//注意这里 45 } 46 clientSocket.close(; 47 48 } catch (Exception ex { 49 //logs 50 } 51 52 } 53 } 54 55 class SayThread implements Runnable { 56 private OutputStream os; 57 58 SayThread(OutputStream outputStream { 59 this.os = outputStream; 60 } 61 62 @Override 63 public void run( { 64 try { 65 os.write("client connect success!!!".getBytes(; 66 Scanner inputScanner = new Scanner(System.in; 67 while (true { 68 String str = inputScanner.nextLine(; 69 os.write(str.getBytes(; 70 os.flush(; 71 } 72 73 } catch (Exception ex { 74 //logs 75 } 76 77 } 78 }

效果如图,我们可以通过这两个程序进行聊天:

客户端截图:

下面就是BIO模型的简示图

在这个程序(模型)中,存在两个阻塞的点:(防盗连接:本文首发自http://www.cnblogs.com/jilodream/
1、服务器在等待客户端接入,也就是accept的地方。(服务端代码的 18行)
2、服务器或客户端在等待socket写入指令的地方。(服务端代码的42,49行,客户端代码37,44行)
如图,线程虽然是RUNNING状态,但是却不继续执行了:

BIO是Jdk 1.0 时就引入的网络编程模型,Jdk1.4之后,引入了NIO(我会在后文中详细介绍),来解决阻塞问题,让线程不再等待。
那有了NIO是不是就不再需要,BIO了呢?(防盗连接:本文首发自http://www.cnblogs.com/jilodream/
并不是,BIO的优点是可以通过增加线程进行业务隔离,逻辑清晰,编码和模型实现也都非常简单。
缺点则是如果想提高性能,需要增加多线程支撑,即使如此仍然存在阻塞点导致性能瓶颈上限比较低。
因此在资源满足的情况下,连接数量少时,是比较推荐使用BIO的。

 

编程笔记 » Java网络编程----通过实现简易聊天工具来聊聊BIO

赞同 (60) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽