Java网络编程 -- BIO 阻塞式网络编程
阻塞IO的含义
阻塞(blocking)IO :阻塞是指结果返回之前,线程会被挂起,函数只有在得到结果之后(或超时)才会返回
非阻塞(non-blocking)IO :非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回
同步(synchronous)IO :应用阻塞在发送或接受数据的状态,直至数据成功传输(或返回失败),简单来说就是必须一件一件事做,等前一件做完了才能做下一件事
异步(asynchronous)IO :应用发送或接受数据后立即返回,实际处理这个调用的程序在完成后,通过状态、通知和回调来通知调用者
阻塞和非阻塞是获取资源的方式,同步和异步是程序如何处理资源的逻辑。
BIO网络编程
首先我们来看一段最基础的Java网络编程代码示例:
服务器端代码示例:
public class BIOServerV1 {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务器启动成功");
while (!serverSocket.isClosed()) {
Socket request = serverSocket.accept(); // 阻塞
System.out.println("收到新连接:" + request.toString());
try {
InputStream inputStream = request.getInputStream(); // 获取数据流
BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
String message;
while ((message = bufferedReader.readLine()) != null) {
if (message.length() == 0) {
break;
}
System.out.println("消息内容为:" + message);
}
System.out.println("收到数据,来自:" + request.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
request.close();
}
}
serverSocket.close();
}
}
客户端代码示例:
public class BIOClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 8080);
OutputStream outputStream = socket.getOutputStream();
Scanner scanner = new Scanner(System.in);
System.out.println("请输入:");
String message = scanner.nextLine();
outputStream.write(message.getBytes(Charset.forName("UTF-8")));
scanner.close();
socket.close();
}
}
这个版本服务器端的代码同一时刻只能支持一个网络连接,在建立连接之后服务端线程会被阻塞,只有在已建立连接的客户端处理完数据关闭连接之后,后续的连接请求才能一个一个的处理,而为了能并发的处理多个请求我们在下一个版本中加入多线程的代码。
public class BIOServerV2 {
private static ExecutorService executorService = Executors.newCachedThreadPool();
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务器启动成功");
while (!serverSocket.isClosed()) {
Socket request = serverSocket.accept();
System.out.println("收到新连接:" + request.toString());
// 多线程接收多个连接
executorService.submit(
() -> {
try {
InputStream inputStream = request.getInputStream();
BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
String message;
while ((message = bufferedReader.readLine()) != null) {
if (message.length() == 0) {
break;
}
System.out.println("消息内容为:" + message);
}
System.out.println("收到数据,来自:" + request.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
request.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
serverSocket.close();
}
}
这个版本的代码在加入多线程后可以并发的处理多个连接,但是它只能处理Java客户端的连接不能处理浏览器端的连接,而为了能与浏览器端交互我们需要了解HTTP协议的内容。
HTTP协议
HTTP协议请求数据包解析
HTTP协议响应数据包解析
HTTP协议响应状态码:
| 状态码 | 描述 |
|---|---|
| 1xx | 临时响应,表示临时响应并需要请求者继续执行操作的状态码 |
| 2xx | 成功,表示成功处理了请求的状态码 |
| 3xx | 重定向,表示要完成请求,需要进一步操作。通常,这些状态码用来重定向 |
| 4xx | 请求错误,这些状态码表示请求可能出错,妨碍了服务器的处理 |
| 5xx | 服务器错误,这些状态码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错 |
BIO网络编程处理浏览器请求
在了解了HTTP协议的内容之后我们就可以依据HTTP协议的内容编写程序来处理浏览器请求。在之前多线程版本的代码之上我们需要对数据根据HTTP协议的内容进行处理,代码示例如下:
public class BIOServerV3 {
private static ExecutorService executorService = Executors.newCachedThreadPool();
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务器启动成功");
while (!serverSocket.isClosed()) {
Socket request = serverSocket.accept();
System.out.println("收到新连接:" + request.toString());
// 多线程接收多个连接
executorService.submit(
() -> {
try {
InputStream inputStream = request.getInputStream();
BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
String message;
while ((message = bufferedReader.readLine()) != null) {
if (message.length() == 0) {
break;
}
// 拿到消息后可以解析消息拿到请求方法,请求数据等内容
System.out.println("消息内容为:" + message);
}
System.out.println("收到数据,来自:" + request.toString());
// 根据HTTP协议响应数据包返回数据给浏览器
OutputStream outputStream = request.getOutputStream();
outputStream.write("HTTP/1.1 200 OK\r\n".getBytes());
outputStream.write("Content-Length: 11\r\n\r\n".getBytes());
outputStream.write("Hello World".getBytes());
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
request.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
serverSocket.close();
}
}
以上就是Java BIO网络编程的基本内容,对于BIO来说一个请求对应一个线程,上下文切换占用的资源很重,同时由于大量并发情况下,其他接入的消息,只能一直等待,而目前对于性能,响应速度等的却要求越老越高,BIO网络编程使用的已经越来越少。使用的比较多的是Java NIO网络编程,该部分内容我们将在下一部分继续。

Java网络编程 -- BIO 阻塞式网络编程的更多相关文章
- UNIX网络编程——非阻塞式I/O(套接字)
套接字的默认状态是阻塞的.这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待相应的操作完成.可能阻塞的套接字调用可分为以下4类: (1)输入操作,包括read,readv,rec ...
- java网络通信:同步阻塞式I/O模型(BIO)
缺点:一个线程只能处理一个客户端连接 服务端: public class TimeServer { public static void main(String[] args) throws IOEx ...
- Java IO(3)非阻塞式输入输出(NIO)
在上篇<Java IO(2)阻塞式输入输出(BIO)>的末尾谈到了什么是阻塞式输入输出,通过Socket编程对其有了大致了解.现在再重新回顾梳理一下,对于只有一个“客户端”和一个“服务器端 ...
- CLOS网络的无阻塞条件
交换单元及网络 模拟信号数字化和时分复用基础 交换单元模型基本交换单元 交换网络 2.1模拟信号数字化和分时复用基础 模拟信号是指在是和幅度数值上连续变化的信号 数字信号是指在时间和幅度取值上离散的编 ...
- 阻塞式和非阻塞式IO
有很多人把阻塞认为是同步,把非阻塞认为是异步:个人认为这样是不准确的,当然从思想上可以这样类比,但方式是完全不同的,下面说说在JAVA里面阻塞IO和非阻塞IO的区别 在JDK1.4中引入了一个NIO的 ...
- Linux NIO 系列(03) 非阻塞式 IO
目录 一.非阻塞式 IO 附:非阻塞式 IO 编程 Linux NIO 系列(03) 非阻塞式 IO Netty 系列目录(https://www.cnblogs.com/binarylei/p/10 ...
- 阻塞式简易http服务器
说明 使用java.net包的ServerSocket也是阻塞的,所以下面的实例把ServerSocketChannel换成ServerSocket效果一样. 后台代码 package ...
- 脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?
1.引言 本文接上篇<脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手>,继续脑残式的网络编程知识学习 ^_^. 套接字socket是大多数程序员都非常熟悉的概念,它是计算机 ...
- [转帖]脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?
脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么? http://www.52im.net/thread-1732-1-1.html 1.引言 本文接上篇<脑残式网 ...
随机推荐
- 【题解】【合并序列(水题)P1628】
原题链接 这道题目如果连字符串的基本操作都没学建议不要做. 学了的很简单就可以切,所以感觉没什么难度- 主要讲一下在AC基础上的优化(可能算不上剪枝) 很明显,这道题我们要找的是前缀,那么在字符串数组 ...
- 【分治】黑白棋子的移动-C++
题目描述 有2n个棋子(n≥4)排成一行,开始为位置白子全部在左边,黑子全部在右边,如下图为n=5的情况: ○○○○○●●●●● 移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也 ...
- python菜鸟入门知识
第二章 入门 2.1 输出 2.1.1print() 输出 print(12+21) print((12+21)*9) print(a) # 注意a不可以加引号 2.2变量 1.变量由字母,数字,下划 ...
- 个人永久性免费-Excel催化剂功能第69波-打造最专业易用的商务图表库,即点即用的高级Excel图表
Excel很大一块细分领域是图表,数据分析的末端,数据展示环节,精美恰当的图表,能够为数据分析数据结论带来画龙点睛的一笔.Excel催化剂简单内置了图表库,利用已经做好的模板式的图表示例,可快速复制使 ...
- Excel催化剂开源第29波-在Winform上使用富文本编辑器控件
富文本编辑器,一般都是BS架构专利一般,好像百度有一个开源的比较出名,但无奈这些都只能用在JS上,在BS网页端开发上使用.像Winform开发的VSTO,只能羡慕的份.和一般Winform上用的Ric ...
- 艺赛旗RPA-处理无表头表格
今天写一个demo,要求是对表格数据用价格为key进行排序 样本数据有两种格式: 一.第一行是一个大单元格 处理步骤: 在不变参数的情况下读取表格数据: 结果如下: 可以看见表头: Unnamed: ...
- 脑裂是什么?Zookeeper是如何解决的?
什么是脑裂 脑裂(split-brain)就是"大脑分裂",也就是本来一个"大脑"被拆分了两个或多个"大脑",我们都知道,如果一个人有多个大 ...
- 《C# 语言学习笔记》——委托
委托是一种可以把引用存储为函数的类型. 委托的声明非常类似于函数,但不带函数体,且要使用delegate关键字.委托的声明制定了一个返回类型和一个参数列表. 在定义了委托后,就可以声明该委托类型的变量 ...
- 小白学python-day02-二进制、计算机单位、编程语言分类介绍、
今天是第二天,以下是学习内容总结. 但行努力,莫问前程. ----------------------------------------------------------------------- ...
- python课堂整理1
1.变量 变量只能由字母.数字.下划线组成 特例:1.变量不能用数字开头 2.不能是python的关键字 3.最好不要和python内置的东西重复 让变量名有意义 些 python3的关键字 ...