杰瑞科技汇

java socket调用接口

Java Socket 调用的是 TCP 接口,而不是我们通常所说的 HTTP/HTTPS RESTful API 接口。

java socket调用接口-图1
(图片来源网络,侵删)
  • HTTP/HTTPS RESTful API:这是目前最主流的 Web 接口,它工作在应用层,使用 HTTP 协议(如 GET, POST),数据通常封装在 JSON 或 XML 格式中,我们通常使用 HttpClient (Java 11+)、OkHttpRestTemplate (已不推荐) 等库来调用这类接口。
  • TCP Socket 接口:这是一种更底层的网络通信方式,它工作在传输层,直接建立“客户端-服务器”之间的双向数据通道,通信双方需要自己约定好数据的格式(协议),一个金融交易系统可能会使用 Socket 来进行高速、低延迟的数据交换。

下面,我将分为两部分来回答:

  1. 如何调用 HTTP/HTTPS RESTful API (这是最常见的“接口”)
  2. 如何使用 TCP Socket 调用接口 (严格按照你的问题)

第一部分:如何调用 HTTP/HTTPS RESTful API (推荐方式)

对于绝大多数现代应用开发,你需要的都是这一种,这里我们使用 Java 11 引入的内置 HttpClient,因为它现代、简洁、高效。

示例:使用 java.net.http.HttpClient 调用 GET 和 POST 接口

假设我们要调用一个公共的测试 API:https://jsonplaceholder.typicode.com/posts/1

调用 GET 请求 (获取数据)

java socket调用接口-图2
(图片来源网络,侵删)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class HttpClientGetExample {
    public static void main(String[] args) {
        // 1. 创建 HttpClient 实例
        HttpClient client = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_2) // 使用 HTTP/2
                .connectTimeout(Duration.ofSeconds(10)) // 设置连接超时
                .build();
        // 2. 创建 HttpRequest 请求
        HttpRequest request = HttpRequest.newBuilder()
                .GET() // 显式指定为 GET 请求
                .uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
                .header("Accept", "application/json") // 告诉服务器我们接受 JSON 格式
                .build();
        try {
            // 3. 发送请求并获取响应
            // .bodyHandler 是异步的,这里我们使用同步的 send 方法
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            // 4. 处理响应
            System.out.println("Status Code: " + response.statusCode());
            if (response.statusCode() == 200) {
                System.out.println("Response Body (JSON):");
                System.out.println(response.body());
            } else {
                System.err.println("Request failed with status: " + response.statusCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

调用 POST 请求 (发送数据)

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Map;
public class HttpClientPostExample {
    public static void main(String[] args) {
        HttpClient client = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_2)
                .connectTimeout(Duration.ofSeconds(10))
                .build();
        // 要发送的 JSON 数据
        String jsonBody = "{\n" +
                "  \"title\": \"foo\",\n" +
                "  \"body\": \"bar\",\n" +
                "  \"userId\": 1\n" +
                "}";
        HttpRequest request = HttpRequest.newBuilder()
                .POST(HttpRequest.BodyPublishers.ofString(jsonBody)) // 设置为 POST,并指定请求体
                .uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
                .header("Content-Type", "application/json") // 告诉服务器我们发送的是 JSON
                .header("Accept", "application/json")
                .build();
        try {
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            System.out.println("Status Code: " + response.statusCode());
            if (response.statusCode() == 201) { // POST 成功通常返回 201 Created
                System.out.println("Response Body (Created Post):");
                System.out.println(response.body());
            } else {
                System.err.println("Request failed with status: " + response.statusCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

第二部分:如何使用 TCP Socket 调用接口

这种方式更复杂,因为它涉及到自定义的通信协议,你需要知道服务器端是如何定义数据格式的。

场景假设

假设我们有一个简单的 Socket 服务器,它监听在 localhost:8888 上,它的协议非常简单:

  1. 客户端发送一个字符串,GET_USER:1001
  2. 服务器收到后,如果用户存在,会返回一个 JSON 字符串,{"id":1001,"name":"Alice","age":30}
  3. 如果用户不存在,返回 ERROR:User not found

Java Socket 客户端实现

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketClientExample {
    public static void main(String[] args) {
        String hostname = "localhost";
        int port = 8888;
        try (Socket socket = new Socket(hostname, port)) {
            System.out.println("Connected to server on " + hostname + ":" + port);
            // 1. 获取输出流,用于向服务器发送数据
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            // 2. 获取输入流,用于读取服务器的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            // 3. 准备要发送的请求 (遵循我们约定的协议)
            String request = "GET_USER:1001";
            System.out.println("Sending request: " + request);
            out.println(request); // 发送请求
            // 4. 读取服务器的响应
            String response = in.readLine();
            System.out.println("Received response from server:");
            System.out.println(response);
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host " + hostname);
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to " +
                    hostname + ". Is the server running?");
            e.printStackTrace();
        }
    }
}

代码解析

  1. new Socket(hostname, port):这是核心步骤,它会尝试连接到指定主机和端口,如果连接失败(如服务器未启动),会抛出 IOException
  2. PrintWriter:我们用它来方便地向服务器发送字符串。true 参数表示自动刷新,这样每次调用 println() 后数据都会立即发送出去。
  3. BufferedReader:我们用它来高效地从服务器读取响应,按行读取。
  4. out.println(request):将请求字符串发送给服务器。
  5. in.readLine():阻塞式地等待并读取服务器返回的一行数据。
  6. try-with-resourcestry (Socket socket = ...) 语句会自动在 try 块结束后关闭 Socket,以及通过它获取的 InputStreamOutputStream,防止资源泄漏。

更复杂的协议处理 (示例)

在实际应用中,协议可能更复杂,比如包含消息头、消息体、长度等,这时你需要手动解析这些数据。

java socket调用接口-图3
(图片来源网络,侵删)

假设协议: [总长度][消息类型][消息体] 00024GET_USER:1001 (总长度是 24)

// ... (获取 socket, in, out 的代码相同)
// 1. 发送复杂请求
String complexRequest = "GET_USER:1001";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
// 写入消息体
dos.writeBytes(complexRequest);
int bodyLength = baos.size();
// 构造完整协议包
ByteArrayOutputStream finalBaos = new ByteArrayOutputStream();
DataOutputStream finalDos = new DataOutputStream(finalBaos);
finalDos.writeInt(bodyLength); // 写入4字节的总长度
finalDos.write(baos.toByteArray()); // 写入消息体
byte[] requestData = finalBaos.toByteArray();
out.write(requestData); // 发送字节流
// 2. 读取复杂响应
// 先读取4字节长度
byte[] lengthBytes = new byte[4];
in.readFully(lengthBytes); // 阻塞读取,直到读满4字节
int responseLength = ByteBuffer.wrap(lengthBytes).getInt();
// 再读取指定长度的消息体
byte[] bodyBytes = new byte[responseLength];
in.readFully(bodyBytes);
String response = new String(bodyBytes, StandardCharsets.UTF_8);
System.out.println("Received complex response: " + response);
// ... (关闭流)

总结与对比

特性 HTTP/HTTPS API (HttpClient) TCP Socket API
协议层 应用层 (HTTP/HTTPS) 传输层 (TCP)
标准性 高度标准化,全球通用,有丰富的工具和库支持。 自定义协议,需要客户端和服务器自己定义数据格式。
使用场景 Web 应用、移动 App、微服务之间的绝大多数通信。 高性能计算、金融交易、游戏服务器、物联网设备、与遗留系统集成。
复杂度 ,封装了所有细节,开发者只需关注 URL、方法、头和体。 ,需要处理连接、数据序列化/反序列化、错误处理、心跳保活等。
依赖 Java 内置 (Java 11+) 或第三方库 (OkHttp, Retrofit)。 Java 内置 (java.net.Socket)。
数据格式 通常是 JSON, XML, Form 表单。 任意自定义,如二进制、纯文本、Protobuf 等。
  • 如果你需要调用的是一个现代的 Web 服务(REST API),请毫不犹豫地使用 HttpClient
  • 如果你要连接的是一个使用 TCP Socket 的特定服务(如某些金融终端、游戏服务器),或者你需要实现一个最高性能、最低延迟的内部通信,那么才需要使用原始的 Socket API。
分享:
扫描分享到社交APP
上一篇
下一篇