从TCP握手到Retrofit/OkHttp原理
// AndroidTCPClientActivity.java
import java.io.*;
import java.net.*;
public class AndroidTCPClientActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(() -> {
try {
// 1. 创建Socket对象(本地端口由系统自动分配)
Socket socket = new Socket();
// 2. 设置连接超时(避免无限等待)
socket.setSoTimeout(5000);
// 3. 指定要连接的服务器地址和端口
InetSocketAddress serverAddress = new InetSocketAddress("echo.websocket.org", 80);
// 4. 触发三次握手的第一步(SYN包发送)
socket.connect(serverAddress); // 触发第一次握手(SYN包发送)
// 5. 三次握手已完成(连接建立)
// 此处已通过三次握手,连接建立成功
// 6. 获取输入输出流进行通信
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 7. 发送数据到服务器
writer.write("Hello");
writer.flush();
// 8. 从服务器接收响应
String response = reader.readLine();
Log.d("TCPClient", "Response: " + response);
// 9. 关闭连接
socket.close(); // 触发四次挥手过程
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
socket.connect()方法触发内核发送SYN包(第一次握手)connect()方法返回时,表示三次握手已完成(第三次握手)<uses-permission android:name="android.permission.INTERNET"/>// 伪代码:Android内核TCP超时重传逻辑
public void synRetransmission() {
int retransmissionCount = 0; // 默认重传次数
long baseRTO = 1000; // 初始重传时间
while (retransmissionCount < 3) { // 默认最多重传3次
// 1. 发送SYN包
sendSynPacket();
// 2. 设置超时时间(使用指数退避算法)
long rto = baseRTO * (1 << retransmissionCount); // RTO = SRTT + max(G, 4×RTTVAR)
// 3. 等待ACK
if (waitForAck(rto)) {
break; // 成功
} else {
retransmissionCount++;
if (retransmissionCount >= 3) {
// 若3次重传均失败,触发RST报文
sendRstPacket();
throw new IOException("Connection timed out");
}
}
}
}
Socket.setSoTimeout()设置自定义超时时间// AndroidTCPServerService.java
public class AndroidTCPServerService extends Service {
private ServerSocket serverSocket;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
try {
// 1. 创建ServerSocket并绑定端口
serverSocket = new ServerSocket(8080); // 服务端监听8080端口
Log.d("TCPServer", "Server started on port 8080");
// 2. 循环等待客户端连接
while (!Thread.currentThread().isInterrupted()) {
// 此处进入阻塞状态,等待客户端连接
Socket clientSocket = serverSocket.accept();
// 3. 处理客户端连接
handleClientConnection(clientSocket);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleClientConnection(final Socket clientSocket) {
new Thread(() -> {
try {
// 4. 获取输入输出流
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
// 5. 读取客户端数据
String request = reader.readLine();
Log.d("TCPServer", "Received: " + request);
// 6. 发送响应
writer.write("Hello from server");
writer.flush();
// 7. 主动关闭连接触发四次挥手
clientSocket.close(); // 触发四次挥手
} catch (IOException e) {
e.printStackTrace();
try {
clientSocket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}).start();
}
@Override
public void onDestroy() {
super.onDestroy();
try {
serverSocket.close(); // 服务端关闭时也会触发四次挥手
} catch (IOException e) {
e.printStackTrace();
}
}
// 服务端启动代码
public class StartServerActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, AndroidTCPServerService.class);
startService(intent);
}
}
}
| 方法 | 行为 | 对四次挥手的影响 |
|---|---|---|
shutdownOutput() |
关闭输出流,但保持输入流打开 | 触发三次挥手(客户端发送FIN,服务端发送ACK后发送FIN) |
close() |
关闭输入和输出流 | 触发四次挥手(双方发送FIN和ACK) |
<uses-permission android:name="android.permission.INTERNET"/>// OkHttpExampleActivity.java
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.netUnknownHostException;
import java.util.Date;
import java.util.zip.GZIPInputStream;
public class OkHttpExampleActivity extends AppCompatActivity {
private TextView resultTextView;
private Button requestButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_okhttp);
resultTextView = findViewById(R.id.result_text);
requestButton = findViewById(R.id.request_button);
requestButton.setOnClickListener(v -> {
// 1. 配置OkHttpClient并添加自定义拦截器
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new ConnectionInfoInterceptor())
.build();
// 2. 创建GET请求
Request request = new Request.Builder()
.url("https://httpbin.org/get")
.build();
// 3. 发起异步请求
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("OkHttp", "Request failed", e);
runOnUiThread(() -> resultTextView.setText("Failed: " + e.getMessage()));
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String body = response.body().string();
runOnUiThread(() -> resultTextView.append("\nResponse: " + body));
}
});
});
}
// 自定义拦截器:打印连接信息
private class ConnectionInfoInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 获取连接信息(仅在首次建立连接时有效)
Connection connection = chain.connection();
Socket socket = connection != null ? connection.socket() : null;
// 打印连接建立时间
String connectionTime = "New connection";
if (socket != null && socket.isBound()) {
connectionTime = "Connection reused";
}
// 打印本地端口
int localPort = -1;
if (socket != null) {
try {
localPort = socket.getLocalPort(); // 获取本地端口
String localAddress = socket.getLocalAddress().getHostAddress();
// 打印连接信息
Log.d("OkHttp", "Local port: " + localPort + " (" + localAddress + ") | " + connectionTime);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
// 执行请求
return chain.proceed(request);
}
}
// 查看连接池配置
public void showConnectionPoolConfig() {
// 获取连接池配置
ConnectionPool pool = client.connectionPool();
int maxIdleConnections = pool.maxIdleConnections(); // 默认5个空闲连接
long keepAliveDuration = pool.keepAliveDuration(); // 默认5分钟
Log.d("OkHttp", "Connection pool config: maxIdle=" + maxIdleConnections + ", keepAlive=" + keepAliveDuration + "ms");
}
}
复用条件:
连接生命周期:
<uses-permission android:name="android.permission.INTERNET"/>// ApiService接口定义
public interface ApiService {
// 使用@GET注解定义请求方法
@GET("get")
// 使用Call表示异步请求
Call get();
}
// HttpBinResponse数据模型
public class HttpBinResponse {
private String url;
private String headers;
// 需要提供getter和setter方法
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getHeaders() { return headers; }
public void setHeaders(String headers) { this.headers = headers; }
}
// Retrofit使用示例
public class RetrofitExampleActivity extends AppCompatActivity {
private TextView resultTextView;
private Button requestButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_retrofit);
resultTextView = findViewById(R.id.result_text);
requestButton = findViewById(R.id.request_button);
// 创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://httpbin.org/")
.addConverterFactory(GsonConverterFactory.create())
.build();
// 动态代理创建ApiService实现
ApiService apiService = retrofit.create(ApiService.class);
requestButton.setOnClickListener(v -> {
// 发起异步请求
Call call = apiService.get();
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("Retrofit", "Request failed", e);
runOnUiThread(() -> resultTextView.setText("Failed: " + e.getMessage()));
}
@Override
public void onResponse(Call call, Response response) {
HttpBinResponse body = response.body();
runOnUiThread(() -> resultTextView.append("\nURL: " + body.getUrl()));
}
});
});
}
}
// 伪代码:Retrofit核心动态代理实现
public class Retrofit {
// 缓存ServiceMethod实例
private final Map<Method, ServiceMethod<?>> methodCache = new ConcurrentHashMap<>();
// 创建接口的代理实例
public <T> T create(Class<T> service) {
// 1. 创建代理工厂
ServiceMethod adaptations = new ServiceMethod adaptations();
// 2. 动态生成代理类
return (T) Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[]{service},
new RetrofitProxy(adaptations)
);
}
// 代理处理器类
private class RetrofitProxy implements InvocationHandler {
private final OkHttp okHttpClient;
public Object invoke(Object proxy, Method method, Object[] args) {
// 1. 从缓存获取ServiceMethod
ServiceMethod<?> serviceMethod = methodCache.get(method);
if (serviceMethod == null) {
// 2. 解析方法注解生成ServiceMethod
serviceMethod = ServiceMethod.parseAnnotations(Retrofit this, method);
methodCache.put(method, serviceMethod);
}
// 3. 调用ServiceMethod执行请求
return serviceMethod.invoke(args);
}
}
// ServiceMethod类结构
public static class ServiceMethod<T> {
private final String httpMethod; // 如GET、POST
private final String path; // 如/get
private final Converter<Call<T>, T> responseConverter;
// 解析方法注解生成请求模板
public static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 1. 解析HTTP方法注解(@GET、@POST等)
// 2. 解析URL注解(@Url、@GET等)
// 3. 解析参数注解(@Path、@Query等)
// 4. 解析返回类型注解(@Body等)
// 5. 创建请求工厂(RequestFactory)
// 6. 创建响应转换器(Converter)
return new ServiceMethod<>(...);
}
// 执行请求并返回Call对象
public Object invoke(Object[] args) {
// 1. 创建请求(Request)
Request request = createRequest(args);
// 2. 创建OkHttpCall并返回
return new OkHttpCall<>(request);
}
}
// OkHttpCall执行请求
public class OkHttpCall<T> implements Call<T> {
private final Request request;
private final Response response;
public OkHttpCall(Request request) {
this.request = request;
}
// 异步执行请求
public void enqueue(Callback<T> callback) {
// 1. 通过OkHttpClient执行请求
// 2. 处理响应并转换为Java对象
// 3. 调用回调方法
}
}
}
<uses-permission android:name="android.permission.INTERNET"/>// NetworkCheckActivity.java
public class NetworkCheckActivity extends AppCompatActivity {
private Button checkButton;
private TextView resultTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network_check);
checkButton = findViewById(R.id.check_button);
resultTextView = findViewById(R.id.result_text);
// 配置Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://httpbin.org/")
.addConverterFactory(GsonConverterFactory.create())
.client(configureOkHttpClient())
.build();
ApiService apiService = retrofit.create(ApiService.class);
checkButton.setOnClickListener(v -> {
// 1. 检查网络状态
boolean isNetworkAvailable = checkNetwork();
resultTextView.append("\nNetwork available: " + isNetworkAvailable);
if (isNetworkAvailable) {
// 2. 发起Retrofit请求
apiService.get().enqueue(new Callback<HttpBinResponse>() {
@Override
public void onFailure(Call<HttpBinResponse> call, IOException e) {
Log.e("NetworkCheck", "Request failed", e);
runOnUiThread(() -> resultTextView.append("\nFailed: " + e.getMessage()));
}
@Override
public void onResponse(Call<HttpBinResponse> call, Response<HttpBinResponse> response) {
HttpBinResponse body = response.body();
runOnUiThread(() -> {
resultTextView.append("\nURL: " + body.getUrl());
resultTextView.append("\n五元组信息: 请使用adb命令查看");
});
}
});
// 3. 打印五元组信息(需在电脑上执行)
Log.d("NetworkCheck", "要查看TCP连接的五元组信息,请执行以下命令:");
Log.d("NetworkCheck", "adb shell cat /proc/net/tcp | grep 0x10080"); // 0x10080是8080的十六进制
}
});
}
// 检查网络状态
private boolean checkNetwork() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
// 配置OkHttpClient并添加连接信息拦截器
private OkHttpClient configureOkHttpClient() {
return new OkHttpClient.Builder()
.addInterceptor(new ConnectionInfoInterceptor())
.build();
}
// 自定义拦截器:打印连接信息
private class ConnectionInfoInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 获取连接信息
Connection connection = chain.connection();
Socket socket = connection != null ? connection.socket() : null;
// 打印连接建立时间
String connectionTime = "New connection";
if (socket != null && socket.isBound()) {
connectionTime = "Connection reused";
}
// 打印本地端口
int localPort = -1;
if (socket != null) {
try {
localPort = socket.getLocalPort(); // 获取本地端口
String localAddress = socket.getLocalAddress().getHostAddress();
// 打印连接信息
Log.d("OkHttp", "Local port: " + localPort + " (" + localAddress + ") | " + connectionTime);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
// 执行请求
return chain.proceed(request);
}
}
// 解析/proc/net/tcp中的十六进制地址
private String parseHexAddress(String hexAddress) {
// 示例:0100007F:001B → 127.0.0.1:27
hexAddress = hexAddress.replace(":", "");
String ipHex = hexAddress.substring(0, 8);
String portHex = hexAddress.substring(8, 12);
// IP地址解析
String ip = "";
for (int i = 0; i < 8; i += 2) {
String octetHex = ipHex.substring(i, i + 2);
int octet = Integer.parseInt(octetHex, 16);
ip += octet + ".";
}
ip = ip.substring(0, ip.length() - 1);
// 端口解析
int port = Integer.parseInt(portHex, 16);
return ip + ":" + port;
}
}
执行adb命令:
adb shell cat /proc/net/tcp
解析输出:
01 0100007F:001B 00000000:0000 01 00000000:0000 00:00000000 00000000 100 0 0 10 0
- local address:本地IP和端口(十六进制)
- rem address:远程服务器IP和端口(十六进制)
- state:连接状态(十六进制,如01表示ESTABLISHED)
转换十六进制为十进制:
<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.INTERNET"/>// 使用Connectivity Manager检查网络状态
public boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
// 监听网络变化
public void registerNetworkCallback() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build();
connectivityManager.registerNetworkCallback(request, new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
Log.d("Network", "WiFi或移动数据可用");
}
@Override
public void onLost(Network network) {
Log.d("Network", "网络已断开");
}
});
}
// 配置OkHttpClient的超时参数
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS) // 连接超时
.readTimeout(30, TimeUnit.SECONDS) // 读取超时
.writeTimeout(30, TimeUnit.SECONDS) // 写入超时
.build();
// 使用Retrofit的重试机制
// 通过自定义CallAdapter实现重试逻辑
// 监听网络变化并更新连接
public class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
// 网络发生变化,可以重新连接服务器
Log.d("Network", "网络已切换,正在重新连接...");
reconnectServer();
}
}
private void reconnectServer() {
// 实现网络切换后的重新连接逻辑
}
}
// 注册广播接收器
registerReceiver(new NetworkChangeReceiver(), new IntentFilter(
ConnectivityManager.CONNECTIVITY_ACTION));
<uses-permission android:name="android.permission.INTERNET"/>Android网络通信是一个多层次、高内聚的复杂系统,从底层Linux内核的TCP/IP协议栈,到应用框架层的HTTP客户端和Socket API,再到应用层的Retrofit等网络库。理解这一完整流程对于构建高效、可靠的Android应用至关重要。
通过深入理解Android网络通信的实现原理和优化策略,开发者可以更好地利用Android平台的网络功能,构建高效、安全、可靠的移动应用。无论是使用Socket实现底层TCP通信,还是使用Retrofit等框架简化HTTP请求,都应基于对网络协议和系统约束的深入理解,做出最适合应用需求的决策。