在AndroidManifest.xml
中添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
若需访问局域网,还需添加:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
Android禁止在主线程执行网络IO操作,需通过以下方式处理:
| 方案 | 说明 |
|———————|———————————————————————-|
| Thread
| 创建新线程执行Socket操作 |
| AsyncTask
| 已过时但可用(API<30) |
| Handler+Thread
| 通过消息机制更新UI |
| Kotlin Coroutine
| 现代推荐方式(协程+withContext(Dispatchers.IO)
) |
| WorkManager
| 适合延迟/周期性任务 |
// 1. 创建Socket连接 Socket socket = new Socket(); SocketAddress serverAddress = new InetSocketAddress("192.168.1.100", 8888); // 替换为服务器IP和端口 socket.connect(serverAddress, 5000); // 设置5秒超时时间 // 2. 获取输入输出流 OutputStream outputStream = socket.getOutputStream(); InputStream inputStream = socket.getInputStream(); // 3. 发送数据 String message = "Hello Server"; outputStream.write(message.getBytes()); outputStream.flush(); // 4. 接收数据 byte[] buffer = new byte[1024]; int len = inputStream.read(buffer); String response = new String(buffer, 0, len); // 5. 关闭资源 outputStream.close(); inputStream.close(); socket.close();
public class TcpClient { private static final String SERVER_IP = "192.168.1.100"; // 服务器IP private static final int SERVER_PORT = 8888; // 服务器端口 private static final int TIMEOUT = 5000; // 超时时间(ms) public static void startConnection() { new Thread(() -> { try { // 创建Socket并连接 Socket socket = new Socket(); socket.connect(new InetSocketAddress(SERVER_IP, SERVER_PORT), TIMEOUT); // 获取流对象 OutputStream os = socket.getOutputStream(); InputStream is = socket.getInputStream(); // 发送数据 String sendData = "Request Data"; os.write(sendData.getBytes()); os.flush(); // 接收数据 byte[] buffer = new byte[1024]; int readLen = is.read(buffer); String receiveData = new String(buffer, 0, readLen); // 打印结果(实际应通过Handler更新UI) Log.d("TCP_CLIENT", "Received: " + receiveData); // 关闭资源 is.close(); os.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); } }
# 在PC端运行(需安装Python) python -m http.server 8888 # HTTP服务器(非TCP)
# tcp_server.py import socket HOST = '0.0.0.0' # 监听所有接口 PORT = 8888 # 端口号 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() print(f"Server listening on {PORT}...") conn, addr = s.accept() with conn: print(f"Connected by {addr}") while True: data = conn.recv(1024) if not data: break print(f"Received: {data.decode()}") conn.sendall(b"Echo: " + data) # 回显数据
# 在终端运行(模拟TCP服务器) nc -l -p 8888 # 监听8888端口
问题现象 | 原因分析 | 解决方案 |
---|---|---|
NetworkOnMainThreadException |
主线程执行网络操作 | 移至子线程或使用异步框架 |
ECONNREFUSED |
服务器未启动/IP/端口错误 | 检查服务器状态及配置信息 |
Permission denied |
未声明INTERNET权限 | 添加<uses-permission> |
数据接收不完整 | 未正确处理流结束或缓冲区大小不当 | 循环读取直到流结束 |
SSL握手失败 | 使用HTTPS但未配置证书 | 启用SSLSocket并加载证书 |
Q1:TCP通信与UDP通信有什么区别?何时选择TCP?
A:TCP(传输控制协议)提供可靠连接,保证数据顺序和完整性,适用于需要稳定传输的场景(如文件传输、即时通讯),UDP(用户数据报协议)无连接确认,速度快但不可靠,适用于实时性要求高且允许少量丢包的场景(如在线游戏、视频直播)。
Q2:如何实现Android与服务器的SSL加密通信?
A:需使用SSLSocket
替代普通Socket,步骤如下:
// 创建SSLContext并信任所有证书(仅测试环境) SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new SecureRandom());
// 创建SSLSocket
SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket();
sslSocket.connect(new InetSocketAddress(SERVER_IP, SERVER_PORT), TIMEOUT);
正式环境需验证服务器证书合法性,避免中间人攻击