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

- HTTP/HTTPS RESTful API:这是目前最主流的 Web 接口,它工作在应用层,使用 HTTP 协议(如
GET,POST),数据通常封装在 JSON 或 XML 格式中,我们通常使用HttpClient(Java 11+)、OkHttp或RestTemplate(已不推荐) 等库来调用这类接口。 - TCP Socket 接口:这是一种更底层的网络通信方式,它工作在传输层,直接建立“客户端-服务器”之间的双向数据通道,通信双方需要自己约定好数据的格式(协议),一个金融交易系统可能会使用 Socket 来进行高速、低延迟的数据交换。
下面,我将分为两部分来回答:
- 如何调用 HTTP/HTTPS RESTful API (这是最常见的“接口”)
- 如何使用 TCP Socket 调用接口 (严格按照你的问题)
第一部分:如何调用 HTTP/HTTPS RESTful API (推荐方式)
对于绝大多数现代应用开发,你需要的都是这一种,这里我们使用 Java 11 引入的内置 HttpClient,因为它现代、简洁、高效。
示例:使用 java.net.http.HttpClient 调用 GET 和 POST 接口
假设我们要调用一个公共的测试 API:https://jsonplaceholder.typicode.com/posts/1
调用 GET 请求 (获取数据)

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 上,它的协议非常简单:
- 客户端发送一个字符串,
GET_USER:1001。 - 服务器收到后,如果用户存在,会返回一个 JSON 字符串,
{"id":1001,"name":"Alice","age":30}。 - 如果用户不存在,返回
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();
}
}
}
代码解析
new Socket(hostname, port):这是核心步骤,它会尝试连接到指定主机和端口,如果连接失败(如服务器未启动),会抛出IOException。PrintWriter:我们用它来方便地向服务器发送字符串。true参数表示自动刷新,这样每次调用println()后数据都会立即发送出去。BufferedReader:我们用它来高效地从服务器读取响应,按行读取。out.println(request):将请求字符串发送给服务器。in.readLine():阻塞式地等待并读取服务器返回的一行数据。try-with-resources:try (Socket socket = ...)语句会自动在try块结束后关闭Socket,以及通过它获取的InputStream和OutputStream,防止资源泄漏。
更复杂的协议处理 (示例)
在实际应用中,协议可能更复杂,比如包含消息头、消息体、长度等,这时你需要手动解析这些数据。

假设协议: [总长度][消息类型][消息体]
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 的特定服务(如某些金融终端、游戏服务器),或者你需要实现一个最高性能、最低延迟的内部通信,那么才需要使用原始的
SocketAPI。
