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. 《MySQL是怎样运行的》第六章小结

  2. [极客大挑战 2019]BuyFlag 1

    好吧,又是一道违背我思想的题目,哦不哦不不对,是本人操作太傻了 首先进入主页面 没有发现什么奇怪的东西,查看源代码,搜索.php 可以看到有一个pay.php,访问查看 给我们了一些提示 FLAG N ...

  3. Less-7 '))闭合 和 secure_file_priv 配置写入一句话木马

    Less-7使用的文件导出select ... into outfile ....,一个文件上传. mysql安全配置里有一个配置secure_file_priv控制文件的导出导入. secure_f ...

  4. IDEA: 如何导入项目模块 以及 将 Java程序打包 JAR 详细步骤

    IDEA: 如何导入项目模块 以及 将 Java程序打包 JAR 详细步骤 . @ 目录 IDEA: 如何导入项目模块 以及 将 Java程序打包 JAR 详细步骤 IDEA 导入项目模块 Modul ...

  5. 火山引擎 DataLeap:一家企业,数据体系要怎么搭建?

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 导读:经过十多年的发展,数据治理在传统行业以及新兴互联网公司都已经产生落地实践.字节跳动也在探索一种分布式的数据治 ...

  6. 如何解决 Iterative 半监督训练 在 ASR 训练中难以落地的问题丨RTC Dev Meetup

    前言 「语音处理」是实时互动领域中非常重要的一个场景,在声网发起的「RTC Dev Meetup丨语音处理在实时互动领域的技术实践和应用」活动中,来自微软亚洲研究院.声网.数美科技的技术专家,围绕该话 ...

  7. CF1037H Security题解

    根据字典序的定义,位置大的大于长度长的,长度长的大于长度短的. 所以我们贪心,先追求长度长的,再追求后面的位置大的,再追求前面的位置大的. 我们要一个能遍历子串的结构,就选 SAM 得了. 还有个限制 ...

  8. 什么是mvvm?简单介绍它的概念、原理及实现

    1.MVVM的概念 model-view-viewModel,通过数据劫持+发布订阅模式来实现. mvvm是一种设计思想.Model代表数据模型,可以在model中定义数据修改和操作的业务逻辑;vie ...

  9. 处理尚不存在的 DOM 节点

    探索 MutationObserver API 与传统轮询等待最终被创建的节点方法相比的优劣. 有时候,您需要操作尚未存在的 DOM 的某个部分. 出现这种需求的原因有很多,但你最常看到的是在处理第三 ...

  10. Object 通用方法

    Object 通用方法 概览 public final native Class<?> getClass() public native int hashCode() public boo ...