前文提到了 Go 语言版本的 Unix 套接字的实践,作为 Java 选手,自然也必须安排上。有了 Go 的经验,Java 写起来也比较容易。
Java 使用 Unix 套接字并不是 JDK 自带的,我们需要引入一个依赖。
<dependency>
<groupId>com.kohlschutter.junixsocket</groupId>
<artifactId>junixsocket-core</artifactId>
<version>2.3.3</version>
</dependency>
相比 Go 语言,Java 的代码略显臃肿了。但对于我来讲,Java 语言熟悉太多了,跟见了亲人似的。
服务端跟前文功能一致,启动服务,接收消息,回复消息。
package com.funtest.unix_socket;
import org.newsclub.net.unix.AFUNIXServerSocket;
import org.newsclub.net.unix.AFUNIXSocketAddress;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* Unix Socket 服务端
*/
public class UnixSocketServer {
public static void main(String[] args) throws IOException {
File socketFile = new File("/Users/oker/logs/temp/unix_socket_example");// 服务端监听的文件
try (ServerSocket server = AFUNIXServerSocket.newInstance()) {// 创建服务端
server.bind(new AFUNIXSocketAddress(socketFile));// 绑定文件
System.out.println("监听文件: " + socketFile);
while (true) {
try (Socket socket = server.accept()) {// 接收客户端连接
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 读取客户端消息
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true)) {// 回复客户端消息
String line;
while ((line = reader.readLine()) != null) {// 循环读取客户端消息
System.out.println("收到消息: " + line);
writer.println("回复: " + line);// 回复消息
}
}
}
}
}
}
}
下面是客户端代码,只是发送消息,打印响应。
package com.funtest.unix_socket;
import org.newsclub.net.unix.AFUNIXSocket;
import org.newsclub.net.unix.AFUNIXSocketAddress;
import java.io.*;
import java.net.Socket;
/**
* Unix Socket 客户端
*/
public class UnixScoketClient {
public static void main(String[] args) throws IOException {
File socketFile = new File("/Users/oker/logs/temp/unix_socket_example");// 服务端监听的文件
try (Socket socket = AFUNIXSocket.newInstance()) {// 创建客户端
socket.connect(new AFUNIXSocketAddress(socketFile));// 连接服务端
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 读取服务端消息
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true)) {// 发送消息给服务端
writer.println("Hello FunTester");
String response = reader.readLine();// 读取服务端响应
System.out.println("收到响应: " + response);
}
}
}
}
经过几次客户端发送消息,下面是服务端打印:
监听文件: /Users/oker/logs/temp/unix_socket_example
收到消息: Hello FunTester
收到消息: Hello FunTester
收到消息: Hello FunTester
下面是客户端打印:
收到响应: 回复: Hello FunTester
进程已结束,退出代码为 0
下面我用 Go 语言的服务端进行测试,Go 服务端打印:
=== RUN TestServer
服务启动...
收到消息: Hello FunTester
Java 客户端打印:
收到响应: null
进程已结束,退出代码为 0
因为原版的 Go 服务端并没有返回响应,现在加上一行代码,增加消息返回。
// handleConnection 处理连接
//
// @Description: 处理连接
// @param conn
func handleConnection(conn net.Conn) {
defer conn.Close() // 关闭连接
buffer := make([]byte, 1024) // 创建一个缓冲区
n, err := conn.Read(buffer) // 读取数据
if err != nil { // 如果读取错误
fmt.Println("读取错误:", err)
return
}
conn.Write([]byte("Hello FunTester")) // 写入数据
fmt.Printf("收到消息: %s\n", string(buffer[:n])) // 打印接收到的数据
}