初探 Java 中的异步 Socket

概述

阻塞模式下的 Socket 编程往往是非常低效的,然而 Java 中的典型 Socket 编程核心采用的正是这种模式。好在 Java 提供了另一种解决方案,通过 Socket Channel 技术实现了非阻塞的异步 Socket 编程。本文将以一个简单的同步 Socket Demo 切入,引出并介绍 Java 中的 Socket Channel 并完成一个 Asynchronous Socket 案例。

文章头图

友情提示:本文还没有写完,明天再说吧(我太难了5555)

一、Socket

在今天的软需分析课上,老师向我们展示了一段用 Java 编写的简单 Socket 通信例程,实现的是基础的 C/S 双向通信。我曾使用 Python 和其它语言开发过 Socket 项目,但为了熟悉 Java 便拿着老师给的代码照着码了一遍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Server
public class ChatServer {
public static void main(String[] args) throws EOFException {
System.out.println("Server is listening on port 8080.");
Thread thread = new Thread(()->{
try(
// Create a socket server
ServerSocket serverSocket = new ServerSocket(8080);
// Get server socket
Socket socket = serverSocket.accept();
// Get socket I/O stream
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
// Get Console buffered Reader
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
){
while (true){
// Input
// Receive message from clients
String iString = inputStream.readUTF();
// Display message received
System.out.println("[Client] " + iString);
// Output
// Get console input
String aString = bufferedReader.readLine();
if(aString.equals("bye"))break;
outputStream.writeUTF(aString);
outputStream.flush();
System.out.println("[Info] " + aString + " has been sent.");
}
}
catch (IOException exp) {
exp.printStackTrace();
}
});
thread.start();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// Client
public class ChatClient {
public static void main(String[] args) {
System.out.println("Client is running.");
Thread thread = new Thread(()->{
try(
// Socket connect
Socket socket = new Socket("localhost",8080);
// Get socket I/O stream
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
// Build a Console buffered Reader
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
)
{
while (true){
// Output
// Get console input
String aString = bufferedReader.readLine();
if(aString.equals("bye"))break;
// Send message
dataOutputStream.writeUTF(aString);
dataOutputStream.flush();
System.out.println("[Info] " + aString + " has been sent.");
// Input
// Receive message from server
String iString = dataInputStream.readUTF();
// Display message received
System.out.println("[Server] " + iString);
}
}catch(UnknownHostException exp){
exp.printStackTrace();
}catch (IOException exp) {
exp.printStackTrace();
}
});
thread.start();
}
}

然而运行结果不尽人意。C/S 之间确实可以相互收发,但彼此间的通信总是被“随机地” “延迟” 送达。课后重新调试时才发现,Java (Server)Socket 类中的 I/O 及 Client 连接均是阻塞的 Synchronous 实现。阻塞模式下的 Socket 编程往往是非常低效的,然而 Java 中的典型 Socket 编程核心采用的正是这种模式。

二、Socket Channel

三、Asynchronous Socket Channel

四、构建一个简易的异步 Socket 演示

五、参考文章与推荐阅读

[1] Java Socket Server Examples (TCP/IP)

[2] Understanding Asynchronous Socket Channels in Java

[3] Java Network Tutorial - Java Asynchronous Socket Channels

如果你觉得文章内容对你有帮助,可以打赏支持一下哦!

0%