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的更多相关文章

  1. Java网络编程以及简单的聊天程序

    网络编程技术是互联网技术中的主流编程技术之一,懂的一些基本的操作是非常必要的.这章主要讲解网络编程,UDP和Socket编程,以及使用Socket做一个简单的聊天软件. 全部代码下载:链接 1.网络编 ...

  2. Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊

    分析: 聊天室需要多个客户端和一个服务端. 服务端负责转发消息. 客户端可以发送消息.接收消息. 消息分类: 群聊消息:发送除自己外所有人 私聊消息:只发送@的人 系统消息:根据情况分只发送个人和其他 ...

  3. java网络编程(4)——udp实现聊天

    UDP可以实现在线聊天功能,我这里就是简单模拟一下: 发送端: package com.seven.udp; import java.io.BufferedReader; import java.io ...

  4. Java网络编程学习笔记

    Java网络编程,我们先来看下面这一张图: 由图可得:想要进行网络编程,首先是服务器端通过ServerSocket对某一个端口进行监听.通过accept来判断是否有客户端与其相连.若成功连上,则通过r ...

  5. 20145225《Java程序设计》 实验五 Java网络编程及安全

    20145225<Java程序设计> 实验五 Java网络编程及安全 实验报告 一.实验内容 基于Java Socket实现安全传输. 基于TCP实现客户端和服务器,结对编程一人负责客户端 ...

  6. Java 网络编程---分布式文件协同编辑器设计与实现

    目录: 第一部分:Java网络编程知识 (一)简单的Http请求 一般浏览网页时,使用的时Ip地址,而IP(Internet Protocol,互联网协议)目前主要是IPv4和IPv6. IP地址是一 ...

  7. Java网络编程技术2

    3. UDP数据报通信 UDP通信中,需要建立一个DatagramSocket,与Socket不同,它不存在“连接”的概念,取而代之的是一个数据报包——DatagramPacket.这个数据报包必须知 ...

  8. Java网络编程技术1

    1. Java网络编程常用API 1.1 InetAddress类使用示例 1.1.1根据域名查找IP地址 获取用户通过命令行方式指定的域名,然后通过InetAddress对象来获取该域名对应的IP地 ...

  9. Java网络编程和NIO详解9:基于NIO的网络编程框架Netty

    Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introd ...

  10. Java网络编程和NIO详解6:Linux epoll实现原理详解

    Java网络编程和NIO详解6:Linux epoll实现原理详解 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO h ...

随机推荐

  1. 使用Git进行版本控制,不同的项目怎么设置不同的提交用户名和邮箱呢?

    1.全局设置用户名和邮箱 因为平时除了开发公司项目还会写自己的项目或者去维护开源项目,一般情况下,公司会要求提交代码时使用自己的真名或者拼音和公司邮箱,以前就只会设置全局用户名或邮箱如下 git co ...

  2. SpringBoot笔记--自动配置(高级内容)(上集)

    原理分析 自动配置 Condition--增加的条件判断功能 来一个案例说明: 具体实现: 没有要求的话,就是这样的: Config.java User.java SpringLearnApplica ...

  3. 在jsp页面int和String类型的相互转换

    浅浅地来做一个对比吧! .java文件 int转成string类型:String s=String.valueOf(int m); String转成int类型:int m=Integer.parseI ...

  4. Activiti7开发(二)-流程定义

    目录 1.部署流程模型为流程定义 2.挂起/激活流程定义 3.删除流程定义 4.查询流程定义 5.上传并部署流程定义 6.查看流程模型 1.部署流程模型为流程定义 @PostMapping(value ...

  5. Java线程池和Spring异步处理高级篇

    开发过程中我们会遇到很多使用线程池的场景,例如异步短信通知,异步发邮件,异步记录操作日志,异步处理批量Excel解析.这些异步处理的场景我们都可以把它放在线程池中去完成,当然还有很多场景也都可以使用线 ...

  6. ARP协议:网络世界的临门一脚

    大家好,我是风筝. 各位同学肯定见过关于网络的面试题,什么TCP协议和UDP的区别啦,IP协议工作在哪层啊等等,这都是网络中定义的各种协议.这些标准化的协议就是网络分层模型标准化的核心部分.要想搞懂网 ...

  7. 表现标准语言CSS3学习 入门+导入方式

    表现标准语言CSS3学习 入门+导入方式 如何学习: css是什么 css怎么用(快速入门) css选择器(重点+难点) 美化网页(文字.阴影.超链接.列表.渐变...) 盒子模型 浮动 定位 网页动 ...

  8. Django笔记六之外键ForeignKey介绍

    这一篇笔记介绍 Django 系统 model 的外键处理,ForeignKey 以及相应的处理方法. 这是一种一对多的字段类型,表示两张表之间的关联关系. 本篇笔记的目录如下: on_delete ...

  9. 基于Go/Grpc/kubernetes/Istio开发微服务的最佳实践尝试 - 1/3

    基于Go/Grpc/kubernetes/Istio开发微服务的最佳实践尝试 - 1/3 基于Go/Grpc/kubernetes/Istio开发微服务的最佳实践尝试 - 2/3 基于Go/Grpc/ ...

  10. python线程之event事件

    from threading import Thread, Event import time event = Event() def light(): print('红灯亮着,所有车都要等待') t ...