前文提到了 Go 语言版本的 Unix 套接字的实践,作为 Java 选手,自然也必须安排上。有了 Go 的经验,Java 写起来也比较容易。

Java 使用 Unix 套接字并不是 JDK 自带的,我们需要引入一个依赖。

<dependency>
    <groupId>com.kohlschutter.junixsocket</groupId>
    <artifactId>junixsocket-core</artifactId>
    <version>2.3.3</version>
</dependency>

Java 实现

相比 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])) // 打印接收到的数据  
}


↙↙↙阅读原文可查看相关链接,并与作者交流