下面我将从基础到高级,分步详细讲解如何使用 Java Socket 调用接口。

核心概念
- Socket (套接字):是网络通信的端点,它就像是电话机,负责建立连接、发送和接收数据。
- IP 地址:网络中设备的唯一标识,就像是服务家的地址。
- 端口号:设备上运行的应用程序的标识,就像是房子的门牌号,确保数据被送到正确的服务。
- 协议:通信双方约定好的规则,HTTP (超文本传输协议),规定了请求和响应的格式。
第一部分:使用原始 Socket 调用 HTTP 接口
原始 Socket 需要我们自己手动构造符合 HTTP 协议的请求报文,并解析服务器返回的响应报文,这能帮助你深刻理解 Socket 和 HTTP 协议的工作原理。
假设我们要调用一个简单的 HTTP GET 接口:http://example.com/api/getInfo。
客户端代码
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class RawHttpClient {
public static void main(String[] args) {
// 1. 定义服务器的地址和端口
String host = "example.com"; // 或者 IP 地址,如 "127.0.0.1"
int port = 80; // HTTP 默认端口是 80,HTTPS 是 443
// 2. 创建 Socket 对象,尝试连接服务器
// try-with-resources 语句可以自动关闭资源
try (Socket socket = new Socket(host, port);
// 3. 获取输出流,用于向服务器发送请求
OutputStream out = socket.getOutputStream();
// 4. 获取输入流,用于读取服务器返回的响应
InputStream in = socket.getInputStream()) {
// 5. 构造 HTTP 请求报文
// 注意:请求行、请求头、空行、请求体(GET请求通常没有请求体)
String httpRequest = "GET /api/getInfo HTTP/1.1\r\n" + // 请求行
"Host: " + host + "\r\n" + // 请求头 (Host是必须的)
"User-Agent: SimpleJavaClient/1.0\r\n" + // 请求头
"Accept: */*\r\n" + // 请求头
"Connection: close\r\n" + // 请求头 (请求结束后关闭连接)
"\r\n"; // 空行,表示请求头结束
System.out.println("Sending HTTP request:\n" + httpRequest);
// 6. 发送请求
out.write(httpRequest.getBytes());
out.flush(); // 确保数据被立即发送
// 7. 读取并打印响应
System.out.println("\nReading HTTP response:");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
// HTTP响应头和响应体之间也有一个空行
boolean inBody = false;
while ((line = reader.readLine()) != null) {
if (line.isEmpty()) {
inBody = true; // 遇到空行,接下来是响应体
System.out.println(); // 打印空行
continue;
}
if (inBody) {
System.out.println(line); // 打印响应体(通常是JSON或HTML)
} else {
System.out.println("Header: " + line); // 打印响应头
}
}
} catch (UnknownHostException e) {
System.err.println("Unknown host: " + host);
e.printStackTrace();
} catch (IOException e) {
System.err.println("I/O error occurred while connecting to " + host);
e.printStackTrace();
}
}
}
代码解析
- 创建 Socket:
new Socket(host, port)尝试与指定 IP 和端口建立 TCP 连接,这是一个阻塞操作,连接成功后才会继续往下执行。 - 获取流:
OutputStream:用于向服务器写入数据,即发送 HTTP 请求。InputStream:用于从服务器读取数据,即接收 HTTP 响应。
- 构造 HTTP 请求:HTTP 请求有严格的格式,一个简单的 GET 请求包括:
- 请求行:
GET /api/getInfo HTTP/1.1 - 请求头:
Host,User-Agent,Accept等。Host是必须的。 - 空行:一个单独的
\r\n,表示请求头结束。
- 请求行:
- 发送和接收:通过流对象进行数据的读写。
- 解析响应:HTTP 响应也分为响应头和响应体,中间由一个空行隔开,我们逐行读取,直到遇到空行,之后的内容就是服务器返回的数据(JSON 字符串)。
第二部分:使用 HttpURLConnection (更推荐的方式)
手动构造 HTTP 请求非常繁琐且容易出错,Java 标准库提供了 HttpURLConnection 类,它封装了底层的 Socket 操作,让我们能更方便地发送 HTTP 请求。
客户端代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class JdkHttpClient {
public static void main(String[] args) {
// 1. 定义接口的 URL
String urlString = "http://example.com/api/getInfo";
try {
// 2. 创建 URL 对象
URL url = new URL(urlString);
// 3. 打开连接,获取 HttpURLConnection 实例
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 4. 设置请求方法 (GET, POST, PUT, DELETE 等)
connection.setRequestMethod("GET");
// 5. 设置请求头
connection.setRequestProperty("User-Agent", "Java-HttpURLConnection/1.0");
connection.setRequestProperty("Accept", "application/json"); // 告诉服务器我们期望接收JSON数据
// 6. 获取响应码 (200表示成功,404表示未找到等)
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) { // 200
// 7. 获取输入流,读取响应数据
try (BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
// 8. 打印响应结果 (通常是JSON字符串)
System.out.println("Response Body:");
System.out.println(response.toString());
}
} else {
System.out.println("GET request failed. Response Code: " + responseCode);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码解析
HttpURLConnection:它大大简化了工作,我们只需要设置 URL、请求方法、请求头,然后获取响应码和输入流即可。- 优点:
- 简单易用,无需关心底层的 Socket 和 HTTP 协议细节。
- 是 Java 标准库的一部分,无需额外依赖。
- 支持 GET、POST、PUT、DELETE 等多种方法。
- 缺点:
- 功能相对有限,比如对连接池、异步请求的支持不够完善。
- API 设计有些陈旧。
第三部分:使用第三方 HTTP 客户端库 (业界标准)
对于生产环境,我们更推荐使用功能强大、性能优越的第三方 HTTP 客户端库,目前最流行的是 OkHttp 和 Apache HttpClient。

使用 OkHttp (推荐)
OkHttp 是目前 Android 和 Java 开发中最主流的 HTTP 客户端,它支持同步和异步请求,有高效的连接池,使用起来非常简洁。
添加 Maven 依赖:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version> <!-- 请使用最新版本 -->
</dependency>
客户端代码:
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
public class OkHttpExample {
public static void main(String[] args) {
// 1. 创建 OkHttp 客户端 (推荐使用单例模式)
OkHttpClient client = new OkHttpClient();
// 2. 创建 Request 对象
Request request = new Request.Builder()
.url("http://example.com/api/getInfo")
.get() // 显式指定 GET 请求 (默认)
.addHeader("User-Agent", "OkHttp-Example/1.0")
.addHeader("Accept", "application/json")
.build();
// 3. 发送请求并获取响应 (同步方式)
try (Response response = client.newCall(request).execute()) {
// 4. 判断是否成功
if (response.isSuccessful()) {
// 5. 获取响应体
String responseBody = response.body().string();
System.out.println("Response Code: " + response.code());
System.out.println("Response Body:");
System.out.println(responseBody);
} else {
System.out.println("Request failed: " + response.code());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
OkHttp 优点:

- API 简洁现代:Builder 模式非常直观。
- 性能卓越:内置连接池,支持 HTTP/2,减少延迟。
- 功能强大:支持异步请求、文件上传下载、WebSocket 等。
- 自动处理重定向和重试。
总结与对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 原始 Socket | 理解底层原理,控制力最强 | 代码复杂,易出错,需手动处理协议细节 | 学习网络编程,或需要实现自定义协议 |
| HttpURLConnection | 无需额外依赖,标准库支持 | API 陈旧,功能有限,性能一般 | 简单的、非性能敏感的脚本或工具 |
| OkHttp / HttpClient | API 简洁,功能强大,性能优越,生态完善 | 需要引入第三方依赖 | 所有生产环境项目,强烈推荐 |
给你的建议
- 如果你是初学者:先尝试用 原始 Socket 调用一个简单的 HTTP 接口,这能让你明白 HTTP 请求和响应的完整结构。
- 如果你在做日常开发:直接使用
HttpURLConnection就足够了,尤其是在不想引入额外依赖的情况下。 - 如果你在开发商业级、高性能的应用:毫不犹豫地选择 OkHttp,它是目前业界的事实标准,能让你事半功倍,并避免很多坑。
