Java网络编程----通过实现简易聊天工具来聊聊BIO
IO模型即输入输出模型,我们今天主要来聊的是java网络编程中的IO模型---BIO模型。
BIO即阻塞式IO,Blocking IO
blocking [ˈblɒkɪŋ]
v. 堵塞; 阻塞; 堵住(某人的路等); 挡住(某人的视线等); 妨碍; 阻碍;
那究竟什么是阻塞呢?
这里的阻塞和多线程并发控制中,对未持有锁的线程进行同步阻塞是两个概念。更多的是指停滞不前,由于未接受到指令,只能继续等待的意思。
举个经典的例子:(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )
西餐厅中,有1个服务员负责招待。客人进入餐厅中,服务员会根据客人的需要下单或上菜。
当客人A要求点菜时,服务员A开始下单。在这个过程中,客人中间发生了停顿,或者犹豫不决时,服务员只能阻塞等待,不能直接停滞,忙其他的事情。这就是所谓的阻塞。
这样就会有一个问题,服务员只能做完一件事,再做一件事,当有客人B也有要求时,则不能并发执行,这里就是前文中说的多线程同步。
这里存在两个"阻塞",
1、服务员等待指令,只能原地等候下一个指令。
2、由于服务员数量有限,即使其他客人有指令需要下发,服务员依然无法执行。
blocking 属于前者,即服务员只能等待当前客人继续发送指令。
后者则属于多线程同步问题,由于服务员数量有限,无法并发执行事务。
针对于后者,我们一般通过多线程来解决,而前者才是我们今天聊的重点。
大概明白了什么是blocking阻塞之后,我们来看个由blocking IO实现的聊天工具:
Server端代码:
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模型的简示图

服务端在创建好serverSocket之后,会等待客户端socket的连接,当连接成功后,会在服务端和客户端通过Socket进行通信。
在这个程序(模型)中,存在两个阻塞的点:(防盗连接:本文首发自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的更多相关文章
- Java网络编程以及简单的聊天程序
网络编程技术是互联网技术中的主流编程技术之一,懂的一些基本的操作是非常必要的.这章主要讲解网络编程,UDP和Socket编程,以及使用Socket做一个简单的聊天软件. 全部代码下载:链接 1.网络编 ...
- Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊
分析: 聊天室需要多个客户端和一个服务端. 服务端负责转发消息. 客户端可以发送消息.接收消息. 消息分类: 群聊消息:发送除自己外所有人 私聊消息:只发送@的人 系统消息:根据情况分只发送个人和其他 ...
- java网络编程(4)——udp实现聊天
UDP可以实现在线聊天功能,我这里就是简单模拟一下: 发送端: package com.seven.udp; import java.io.BufferedReader; import java.io ...
- Java网络编程学习笔记
Java网络编程,我们先来看下面这一张图: 由图可得:想要进行网络编程,首先是服务器端通过ServerSocket对某一个端口进行监听.通过accept来判断是否有客户端与其相连.若成功连上,则通过r ...
- 20145225《Java程序设计》 实验五 Java网络编程及安全
20145225<Java程序设计> 实验五 Java网络编程及安全 实验报告 一.实验内容 基于Java Socket实现安全传输. 基于TCP实现客户端和服务器,结对编程一人负责客户端 ...
- Java 网络编程---分布式文件协同编辑器设计与实现
目录: 第一部分:Java网络编程知识 (一)简单的Http请求 一般浏览网页时,使用的时Ip地址,而IP(Internet Protocol,互联网协议)目前主要是IPv4和IPv6. IP地址是一 ...
- Java网络编程技术2
3. UDP数据报通信 UDP通信中,需要建立一个DatagramSocket,与Socket不同,它不存在“连接”的概念,取而代之的是一个数据报包——DatagramPacket.这个数据报包必须知 ...
- Java网络编程技术1
1. Java网络编程常用API 1.1 InetAddress类使用示例 1.1.1根据域名查找IP地址 获取用户通过命令行方式指定的域名,然后通过InetAddress对象来获取该域名对应的IP地 ...
- Java网络编程和NIO详解9:基于NIO的网络编程框架Netty
Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introd ...
- Java网络编程和NIO详解6:Linux epoll实现原理详解
Java网络编程和NIO详解6:Linux epoll实现原理详解 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO h ...
随机推荐
- ICSFUZZ:操纵I/O、二进制代码重用以及插桩,来Fuzzing工业控制应用程序
本文系原创,转载请说明出处 Please Subscribe Wechat Official Account:信安科研人,获取更多的原创安全资讯 源码:GitHub - momalab/ICSFu ...
- DVWA-File Inclusion(文件包含)
文件包含漏洞,当我们在一个代码文件想要引入.嵌套另一个代码文件的时候,就是文件包含. 常见的文件包含函数有include require等函数. 这两个函数的区别就是include在包含文件不存在时p ...
- 这篇文章汇聚33个BUG!来挑战一下,看看你能找出来几个?
你好呀,我是歪歪. 前几天看到"Qunar技术沙龙"公众号推送了一篇关于他们举办了一场"Code Review大赛"的文章. 看到 Code Review 我很 ...
- RPA的数字化标签
随着中国经济的飞速发展,"人口红利"也正在不断消失,在过去几十年中,我们已经看到了各种智能化.自动化技术的进步对各行各业产生的巨大影响.但在现代金融行业中,仍然有许多重复.简单.繁 ...
- 使用chatgt(GPT-4)将过程式(的java代码)改成函数式(的elixir代码)
天啦噜太可怕了,之前我还嘲笑chatgpt不会小众语言来着. chatgt(GPT-4)在接收2次prompt后,把过程式(的java代码)改成了函数式(的elixir代码),给出的Elixir代码可 ...
- java异常--自定义异常
java异常--自定义异常 步骤: 创建自定义异常类. 在方法中通过throw关键字抛出异常对象. 处理异常try-catch 捕获并处理,否则在方法声明处通过throws关键字指明抛出给调用者的方法 ...
- 机器学习(三):朴素贝叶斯+贝叶斯估计+BP人工神经网络习题手算|手工推导与习题计算
1.有 1000 个水果样例. 它们可能是香蕉,橙子或其它水果,已知每个水果的 3 种特性:是否偏长.是否甜.颜色是否是黄色 类型 长 不长 甜 不甜 黄色 非黄 Total 香蕉 400 100 3 ...
- ChatGPT如何助力DevOps|用例解读
DevOps 是一种方法论,旨在提高软件开发和 IT 运营团队的协作和效率.DevOps 涉及各种任务和流程的自动化,例如规划.编码.测试.部署.监控和故障排除.然而,其中一些任务和流程仍然有大量任务 ...
- ML - Regression
Regression Machine Learning 机器学习的意义就在于让机器具备找一个函数(function)的能力 Different types of Functions Regressio ...
- 统计模拟实验—R实现(蒲丰投针)
统计模拟实验 统计模拟是数理统计.和计算机科学的结合,是一门综合性学科.在科学研究和生产实际的各个领域中,普遍存在着大量数据的分析处理工作.如何应用数理统计中的方法来解决实际问题,以及如何解决在应用中 ...