同步阻塞I/O 示例
我们使用Java Socket 来实现同步阻塞I/O 的示例。
首先,先编写一个ServerSocket:
package org.example.io.bio;
import org.junit.jupiter.api.Test;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务端示例
*/
public class SocketServerDemo {
@Test
public void serverStart() throws IOException {
//1.创建 ServerSocket
ServerSocket serverSocket = new ServerSocket(8000);
//2.监听连接
while(true){
//接收客户端消息
Socket socket = serverSocket.accept();
System.out.println("服务端接收消息的端口:"+socket.getPort());
//将收到的消息打印出来
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = bufferedReader.readLine();//被阻塞
System.out.println("【ServerSocket】读取内容为:"+line);
//向客户端发送消息
String rtnString = "我收到你的消息了,正在操作中!请稍后\n";
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write(rtnString);
bufferedWriter.flush();
}
}
}
在ServerSocketDemo中,
- 我们创建了一个 ServerSocket,监听8000端口;
- 我们使用了一个
while(true)
的死循环来监听连接的到来; - 接收到Socket 客户端连接后,我们先将服务端的端口打印出来;
- 然后通过
socket.getInputStream
接收客户端的消息内容,并将其转换为BufferedReader
,然后打印出来; - 随后,通过
BufferedWriter
对socket.getOutputStream()
进行包装,将信息“我收到你的消息了,正在操作中!请稍后\n”回复给客户端。(注意:\n 换行符不可少,这是readLine()
读取结束的标识。)
package org.example.io.bio;
import com.alibaba.fastjson2.util.DateUtils;
import org.junit.jupiter.api.Test;
import java.io.*;
import java.net.Socket;
import java.util.Date;
/**
* 客户端示例
*/
public class SocketClientDemo {
@Test
public void send() throws IOException, InterruptedException {
Socket socket = new Socket("localhost",8000);
System.out.println("【"+socket.getLocalPort()+"】连接成功的时间点:"+ DateUtils.format(new Date()));
System.out.println("sleep 20s start....");
Thread.sleep(20000);
System.out.println("sleep 20s end...."+ DateUtils.format(new Date()));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("把来时候的飞机票给报了!\n");
bufferedWriter.flush();
System.out.println("发送消息的时间点:"+ DateUtils.format(new Date()));
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = bufferedReader.readLine();
System.out.println("ServerSocket 回复道:"+line+DateUtils.format(new Date()));
}
}
在SocketClientDemo中,
- 我们首先与
Socket
服务端建立连接; - 接下来通过
sleep
使当前线程暂停 20秒钟;(主要是把机会让给其他线程) - 然后通过
BufferedWriter
包装socket.getOutputStream()
将信息 “把来时候的飞机票给报了!\n” 传递给服务端。 - 接下来接收Socket服务端返回的消息,并将其打印出来。
这里要重点指出的是:
我们会启动两个 SocketClientDemo,来向服务端发起send调用。
其中另外一个把 Thread.sleep(20000)
代码删除掉,目的是让大家看到第一个客户端在sleep 20秒的时候,服务端是阻塞状态,并没有接收第二个客户端的请求。
执行操作:
当第一个含有 Thread.sleep(20000)
代码的客户端发起请求后,第二个客户端随机发起请求;
操作结果:
- 第一个客户端停留20秒后,收到服务端返回消息;
- 服务端在阻塞20秒后,收到第一个服务端的消息,并返回;
- 第二个客户端阻塞20秒后,成功向服务端发送消息;
- 服务端在收到第二个客户端消息后,返回消息;
- 第二个客户端收到服务端消息。
控制台打印结果如下:
//第一个客户端的打印结果
【57156】连接成功的时间点:2024-07-24 11:11:16
sleep 20s start....
sleep 20s end....2024-07-24 11:11:37
发送消息的时间点:2024-07-24 11:11:37
ServerSocket 回复道:我收到你的消息了,正在操作中!请稍后2024-07-24 11:11:37
//服务端打印结果:
服务端接收消息的端口:57156
【ServerSocket】读取内容为:把来时候的飞机票给报了!
服务端接收消息的端口:57185
【ServerSocket】读取内容为:把来时候的飞机票给报了!
//第二个客户端打印结果
【57185】连接成功的时间点:2024-07-24 11:11:23
发送消息的时间点:2024-07-24 11:11:23
ServerSocket 回复道:我收到你的消息了,正在操作中!请稍后2024-07-24 11:11:37
以上就是 《同步阻塞I/O 的代码示例》的全部内容,感谢阅读!