阻塞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 阻塞式网络编程的更多相关文章

  1. UNIX网络编程——非阻塞式I/O(套接字)

    套接字的默认状态是阻塞的.这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待相应的操作完成.可能阻塞的套接字调用可分为以下4类: (1)输入操作,包括read,readv,rec ...

  2. java网络通信:同步阻塞式I/O模型(BIO)

    缺点:一个线程只能处理一个客户端连接 服务端: public class TimeServer { public static void main(String[] args) throws IOEx ...

  3. Java IO(3)非阻塞式输入输出(NIO)

    在上篇<Java IO(2)阻塞式输入输出(BIO)>的末尾谈到了什么是阻塞式输入输出,通过Socket编程对其有了大致了解.现在再重新回顾梳理一下,对于只有一个“客户端”和一个“服务器端 ...

  4. CLOS网络的无阻塞条件

    交换单元及网络 模拟信号数字化和时分复用基础 交换单元模型基本交换单元 交换网络 2.1模拟信号数字化和分时复用基础 模拟信号是指在是和幅度数值上连续变化的信号 数字信号是指在时间和幅度取值上离散的编 ...

  5. 阻塞式和非阻塞式IO

    有很多人把阻塞认为是同步,把非阻塞认为是异步:个人认为这样是不准确的,当然从思想上可以这样类比,但方式是完全不同的,下面说说在JAVA里面阻塞IO和非阻塞IO的区别 在JDK1.4中引入了一个NIO的 ...

  6. Linux NIO 系列(03) 非阻塞式 IO

    目录 一.非阻塞式 IO 附:非阻塞式 IO 编程 Linux NIO 系列(03) 非阻塞式 IO Netty 系列目录(https://www.cnblogs.com/binarylei/p/10 ...

  7. 阻塞式简易http服务器

    说明         使用java.net包的ServerSocket也是阻塞的,所以下面的实例把ServerSocketChannel换成ServerSocket效果一样. 后台代码 package ...

  8. 脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

    1.引言 本文接上篇<脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手>,继续脑残式的网络编程知识学习 ^_^. 套接字socket是大多数程序员都非常熟悉的概念,它是计算机 ...

  9. [转帖]脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

    脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?     http://www.52im.net/thread-1732-1-1.html   1.引言 本文接上篇<脑残式网 ...

随机推荐

  1. Zeppelin 0.6.2使用Spark的yarn-client模式

    Zeppelin版本0.6.2 1. Export SPARK_HOME In conf/zeppelin-env.sh, export SPARK_HOME environment variable ...

  2. 比赛:小奔的矩形solution

    分析: 交叉相乘,然后除以最大公因数(为了减少爆常数的可能性std做了两次,数据很大),得到的两个数相加减二就是答案 代码: var p,q,n,m,a,b,i:int64; begin readln ...

  3. html提示框插件

    最近工作需要,用到各式各样的提示框,寻找了很久,发现一个的第三方的插件很好用,各种样式.接口良好.允许自定义. 官网:http://layer.layui.com/ 使用需要先引入jq1.8以上: & ...

  4. [PTA] 数据结构与算法题目集 6-2 顺序表操作集

    //创建并返回一个空的线性表: List MakeEmpty() { List L; L = (List)malloc(sizeof(struct LNode)); L->Last = -1; ...

  5. python购物车升级版

    各文件内容 前言 功能架构等请参考前一篇博客,此篇博客为进阶版的存代码展示. 详细文件内容 启动文件 starts.py启动文件 import os import sys BASE_DIR = os. ...

  6. C#程序从Excel表格中读取数据并进行处理

    今天做了一个Excel表格数据处理的事情,因为数据量表较大(接近7000条)所以处理起来有点麻烦,于是写了一个程序, 先将程序记下以便将来查找. using System; using System. ...

  7. java练习---7

    //程序员:罗元昊 2017.10.7 import java.util.Scanner; public class L { public static void main(String[] args ...

  8. 学习LayUI时自研的表单参数校验框架

    开发背景&痛点:每次写前端的表单的时候需要对表单里用户填写的内容进行校验,减少服务器压力,提前对已知错误对用户提示.每次会要写很多的if else等等对输入框中的内容进行判断,并对为空.格式不 ...

  9. RobotFramework_1.简介和安装

    RobotFramework_1.简介与安装 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bot ...

  10. 这半年时间学Mysql的总结

    一条sql语句的执行流程 select * from t where id=1 1.mysql执行一条查询语句的流程 1.1客户端输入用户名密码连接mysql服务器 1.2查询这条sql语句有没有对应 ...