Android网络通信深度解析

从TCP握手到Retrofit/OkHttp原理

TCP 三次握手 四次挥手 超时重传 OkHttp 连接池 Retrofit 动态代理 五元组 最佳实践 流程图

目录导航(点击跳转)

一、Android TCP客户端代码与三次握手分析

1 TCP客户端实现代码
// 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();
    }
}
2 三次握手触发点分析
  • socket.connect()方法触发内核发送SYN包(第一次握手)
  • connect()方法返回时,表示三次握手已完成(第三次握手)
  • 该方法会阻塞直到连接建立成功或超时
3 Android网络约束
  • 网络操作必须在子线程中执行,不能在主线程
  • 需要添加网络权限:<uses-permission android:name="android.permission.INTERNET"/>

二、TCP三次握手必要性及弱网下的超时重传机制

1 三次握手必要性
双向通信确认:确保客户端和服务端都能发送和接收数据
  • 客户端发送SYN表明自己可以发送数据
  • 服务端发送SYN+ACK表明自己可以接收和发送数据
  • 客户端最后的ACK确认自己可以接收数据
序列号同步:同步双方的初始序列号(ISN),避免旧连接的残留报文干扰新连接
防止历史残留连接:若服务端收到一个迟到的SYN包(来自旧连接),可能错误地建立新连接
2 弱网下SYN包丢失处理机制
// 伪代码: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");
            }
        }
    }
}
3 弱网环境下的表现
  • 当SYN包丢失时,Android内核会自动触发重传机制
  • 每次重传的超时时间是前一次的两倍(指数退避)
  • 若连续3次重传均失败,系统会放弃连接并抛出异常
  • 开发者可通过 Socket.setSoTimeout()设置自定义超时时间

三、Android TCP服务端代码与四次挥手演示

1 TCP服务端实现代码
// 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);
        }
    }
}
2 四次挥手详细过程
  • 客户端发送FIN:客户端调用close()方法时发送FIN报文,表示不再发送数据
  • 服务端发送ACK:服务端收到FIN后发送ACK确认,并继续处理剩余数据
  • 服务端发送FIN:服务端处理完数据后发送自己的FIN报文
  • 客户端发送ACK:客户端收到FIN后发送ACK确认,并进入TIME_WAIT状态
3 close()与shutdownOutput()的区别
方法 行为 对四次挥手的影响
shutdownOutput() 关闭输出流,但保持输入流打开 触发三次挥手(客户端发送FIN,服务端发送ACK后发送FIN)
close() 关闭输入和输出流 触发四次挥手(双方发送FIN和ACK)
4 Android网络约束
  • 服务端代码必须运行在Service或子线程中,不能在主线程
  • 需要添加网络权限:<uses-permission android:name="android.permission.INTERNET"/>
  • 服务端通常需要绑定到特定端口,且普通应用无法绑定1024以下的端口

四、OkHttp异步GET请求与连接池复用机制

1 OkHttp异步GET请求代码
// 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");
    }
}
2 连接池复用机制
连接存储:ConnectionPool使用ConcurrentHashMap存储RealConnection对象

复用条件:

  • 同一主机地址(Address对象)
  • 协议兼容(HTTP/1.1或HTTP/2)
  • 连接未关闭且空闲时间未超过keepAliveDuration

连接生命周期:

  • 新连接建立后放入池中
  • 空闲连接超过时间会被自动回收
  • 连接池通过maxIdleConnections限制存储数量
3 Android网络约束
  • 网络操作必须在子线程中执行,不能在主线程
  • 需要添加网络权限:<uses-permission android:name="android.permission.INTERNET"/>
  • 主线程网络操作会导致ANR(应用无响应)异常

五、Retrofit动态代理原理与API接口实现

1 Retrofit使用示例
// 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()));
                }
            });
        });
    }
}
2 Retrofit动态代理原理
// 伪代码: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. 调用回调方法
        }
    }
}
3 动态代理执行流程
  • 接口定义:开发者定义接口并添加HTTP注解
  • Retrofit实例化:通过Retrofit.Builder配置基础URL和转换器
  • 代理实例创建:调用retrofit.create()方法,Retrofit生成接口的代理实现类
  • 方法调用拦截:当调用接口方法时,代理处理器捕获调用并解析注解
  • 请求构建:根据注解信息构建完整的HTTP请求(包括URL、参数、Header等)
  • 请求执行:将构建好的请求传递给OkHttp执行
  • 响应处理:OkHttp返回响应后,Retrofit使用转换器将响应转换为Java对象
4 Android网络约束
  • 网络操作必须在子线程中执行,不能在主线程
  • 需要添加网络权限:<uses-permission android:name="android.permission.INTERNET"/>
  • 主线程网络操作会导致ANR(应用无响应)异常

六、综合示例:网络检查与TCP连接五元组打印

1 综合示例代码
// 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;
    }
}
2 TCP连接五元组观察方法

执行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)

转换十六进制为十进制:

  • IP地址:0100007F → 127.0.0.1
  • 端口:001B → 27
3 网络切换影响演示
连接WiFi时:
  • 使用WiFi的IP地址和端口建立连接
  • 低延迟、高带宽
切换到移动数据时:
  • 新连接将使用移动网络的IP地址和端口
  • 可能出现更高的延迟和更低的带宽
  • 原有连接会中断(除非使用连接迁移技术)
4 Android网络约束
  • 网络操作必须在子线程中执行,不能在主线程
  • 需要添加网络权限:<uses-permission android:name="android.permission.INTERNET"/>
  • 主线程网络操作会导致ANR(应用无响应)异常

七、完整网络通信流程图

1 完整网络通信流程图
Android应用层
1
调用Retrofit接口方法
4
获取Call对象并调用enqueue
7
等待响应
10
处理响应数据
13
完成操作并关闭连接
OkHttp/Retrofit框架层
2
解析注解生成HTTP请求
5
通过拦截器添加Header
8
通过连接池获取复用连接
11
发送HTTP请求数据
14
发送FIN包(四次挥手第一步)
16
接收FIN并发送ACK(四次挥手第三步)
Linux内核TCP/IP层
3
发送SYN包(第一次握手)
6
接收SYN-ACK包并发送ACK(第三次握手)
9
建立TCP连接(ESTABLISHED状态)
12
传输数据(应用层与传输层交互)
15
接收FIN并发送ACK(四次挥手第二步)
17
等待2MSL后完全关闭连接(四次挥手第四步)
2 关键流程说明
  • 应用层:开发者使用Retrofit定义接口并发起请求
  • 框架层:Retrofit通过动态代理生成HTTP请求,OkHttp负责底层通信
  • 系统层:Android内核处理TCP握手、挥手和数据传输
  • 网络层:物理网络传输数据包
3 Android网络约束
  • 网络操作必须在子线程中执行,不能在主线程
  • 需要添加网络权限:<uses-permission android:name="android.permission.INTERNET"/>
  • 主线程网络操作会导致ANR(应用无响应)异常

八、Android网络通信最佳实践

1 网络检查最佳实践
// 使用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", "网络已断开");
        }
    });
}
2 弱网环境优化
// 配置OkHttpClient的超时参数
OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(15, TimeUnit.SECONDS) // 连接超时
        .readTimeout(30, TimeUnit.SECONDS)    // 读取超时
        .writeTimeout(30, TimeUnit.SECONDS)   // 写入超时
        .build();

// 使用Retrofit的重试机制
// 通过自定义CallAdapter实现重试逻辑
3 网络切换处理
// 监听网络变化并更新连接
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));
4 Android网络约束
  • 网络操作必须在子线程中执行,不能在主线程
  • 需要添加网络权限:<uses-permission android:name="android.permission.INTERNET"/>
  • 主线程网络操作会导致ANR(应用无响应)异常

九、总结

1 核心要点

Android网络通信是一个多层次、高内聚的复杂系统,从底层Linux内核的TCP/IP协议栈,到应用框架层的HTTP客户端和Socket API,再到应用层的Retrofit等网络库。理解这一完整流程对于构建高效、可靠的Android应用至关重要。

2 实践原则
  • 使用现代网络库:优先使用Retrofit和OkHttp等现代网络库,它们提供了更高效的网络通信实现和更丰富的功能支持
  • 配置合理的网络策略:根据应用需求配置连接超时、读取超时和重试策略,特别是在弱网环境下
  • 处理网络切换:实现网络切换的平滑处理,确保应用在WiFi和移动数据之间无缝切换
  • 优化连接使用:合理使用连接池和连接复用机制,减少TCP握手开销和网络延迟
  • 遵守主线程网络限制:所有网络操作必须在子线程中执行,不能在主线程
3 技术决策建议

通过深入理解Android网络通信的实现原理和优化策略,开发者可以更好地利用Android平台的网络功能,构建高效、安全、可靠的移动应用。无论是使用Socket实现底层TCP通信,还是使用Retrofit等框架简化HTTP请求,都应基于对网络协议和系统约束的深入理解,做出最适合应用需求的决策。