本文将详细介绍在鸿蒙Next中使用Socket进行网络通信的完整流程,包括TCP和UDP两种协议的使用方法,并提供实战示例。
1. Socket通信基础
1.1 TCP与UDP的区别
-
TCP:面向连接、可靠传输、保证数据顺序
-
UDP:无连接、不可靠传输、不保证数据顺序
1.2 鸿蒙中的网络权限配置
在module.json5
文件中添加网络权限:
json
复制
下载
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
2. TCP Socket通信
2.1 TCP客户端实现
typescript
复制
下载
import socket from '@ohos.net.socket';
import common from '@ohos.app.ability.common';
class TCPClient {
private tcpSocket: socket.TCPSocket;
private context: common.BaseContext;
constructor(context: common.BaseContext) {
this.context = context;
this.tcpSocket = socket.constructTCPSocketInstance(this.context);
}
// 连接服务器
async connect(serverIP: string, port: number): Promise<boolean> {
try {
const address: socket.NetAddress = {
address: serverIP,
port: port
};
await this.tcpSocket.bind({
address: '0.0.0.0',
port: 0 // 系统自动分配端口
});
await this.tcpSocket.connect(address);
console.info('TCP连接成功');
return true;
} catch (error) {
console.error(`TCP连接失败: ${error.message}`);
return false;
}
}
// 发送数据
async sendData(data: string): Promise<boolean> {
try {
await this.tcpSocket.send({
data: data
});
console.info('数据发送成功');
return true;
} catch (error) {
console.error(`数据发送失败: ${error.message}`);
return false;
}
}
// 接收数据
setupMessageListener(callback: (data: string) => void) {
this.tcpSocket.on('message', (value: socket.TCPSocketMessageInfo) => {
const message = String.fromCharCode.apply(null, value.message);
console.info(`收到消息: ${message}`);
callback(message);
});
this.tcpSocket.on('close', () => {
console.info('TCP连接已关闭');
});
this.tcpSocket.on('error', (error: Error) => {
console.error(`TCP错误: ${error.message}`);
});
}
// 关闭连接
async close(): Promise<void> {
try {
await this.tcpSocket.close();
console.info('TCP连接已关闭');
} catch (error) {
console.error(`关闭连接失败: ${error.message}`);
}
}
}
2.2 TCP服务器实现
typescript
复制
下载
import socket from '@ohos.net.socket';
import common from '@ohos.app.ability.common';
class TCPServer {
private tcpServer: socket.TCPSocketServer;
private clients: Map<string, socket.TCPSocketConnection> = new Map();
private context: common.BaseContext;
constructor(context: common.BaseContext) {
this.context = context;
this.tcpServer = socket.constructTCPSocketServerInstance(this.context);
}
// 启动服务器
async startServer(port: number): Promise<boolean> {
try {
await this.tcpServer.listen({
address: '0.0.0.0',
port: port,
family: 1 // IPv4
});
console.info(`TCP服务器启动成功,端口: ${port}`);
this.setupConnectionListener();
return true;
} catch (error) {
console.error(`服务器启动失败: ${error.message}`);
return false;
}
}
// 监听客户端连接
private setupConnectionListener() {
this.tcpServer.on('connect', (client: socket.TCPSocketConnection) => {
const clientKey = `${client.remoteInfo.address}:${client.remoteInfo.port}`;
console.info(`客户端连接: ${clientKey}`);
this.clients.set(clientKey, client);
this.setupClientMessageListener(client, clientKey);
});
}
// 监听客户端消息
private setupClientMessageListener(client: socket.TCPSocketConnection, clientKey: string) {
client.on('message', (value: socket.TCPSocketMessageInfo) => {
const message = String.fromCharCode.apply(null, value.message);
console.info(`收到来自${clientKey}的消息: ${message}`);
// 广播消息给所有客户端
this.broadcastMessage(`${clientKey}: ${message}`);
});
client.on('close', () => {
console.info(`客户端断开连接: ${clientKey}`);
this.clients.delete(clientKey);
});
client.on('error', (error: Error) => {
console.error(`客户端错误 ${clientKey}: ${error.message}`);
this.clients.delete(clientKey);
});
}
// 广播消息
async broadcastMessage(message: string): Promise<void> {
for (const [clientKey, client] of this.clients) {
try {
await client.send({
data: message
});
} catch (error) {
console.error(`发送消息到${clientKey}失败: ${error.message}`);
this.clients.delete(clientKey);
}
}
}
// 停止服务器
async stopServer(): Promise<void> {
try {
// 关闭所有客户端连接
for (const [clientKey, client] of this.clients) {
await client.close();
}
this.clients.clear();
await this.tcpServer.off('connect');
await this.tcpServer.close();
console.info('TCP服务器已停止');
} catch (error) {
console.error(`停止服务器失败: ${error.message}`);
}
}
}
3. UDP Socket通信
3.1 UDP客户端实现
typescript
复制
下载
import socket from '@ohos.net.socket';
import common from '@ohos.app.ability.common';
class UDPClient {
private udpSocket: socket.UDPSocket;
private context: common.BaseContext;
constructor(context: common.BaseContext) {
this.context = context;
this.udpSocket = socket.constructUDPSocketInstance(this.context);
}
// 绑定本地端口
async bindLocalPort(port: number): Promise<boolean> {
try {
await this.udpSocket.bind({
address: '0.0.0.0',
port: port
});
console.info(`UDP客户端绑定端口成功: ${port}`);
return true;
} catch (error) {
console.error(`绑定端口失败: ${error.message}`);
return false;
}
}
// 发送数据
async sendData(data: string, remoteIP: string, remotePort: number): Promise<boolean> {
try {
const remoteAddress: socket.NetAddress = {
address: remoteIP,
port: remotePort
};
await this.udpSocket.send({
data: data,
address: remoteAddress
});
console.info(`UDP数据发送成功到 ${remoteIP}:${remotePort}`);
return true;
} catch (error) {
console.error(`UDP数据发送失败: ${error.message}`);
return false;
}
}
// 接收数据
setupMessageListener(callback: (data: string, remoteInfo: socket.SocketRemoteInfo) => void) {
this.udpSocket.on('message', (value: socket.UDPSocketMessageInfo) => {
const message = String.fromCharCode.apply(null, value.message);
console.info(`收到UDP消息 from ${value.remoteInfo.address}:${value.remoteInfo.port}: ${message}`);
callback(message, value.remoteInfo);
});
this.udpSocket.on('error', (error: Error) => {
console.error(`UDP错误: ${error.message}`);
});
}
// 关闭连接
async close(): Promise<void> {
try {
await this.udpSocket.close();
console.info('UDP连接已关闭');
} catch (error) {
console.error(`关闭UDP连接失败: ${error.message}`);
}
}
}
3.2 UDP服务器实现
typescript
复制
下载
import socket from '@ohos.net.socket';
import common from '@ohos.app.ability.common';
class UDPServer {
private udpSocket: socket.UDPSocket;
private context: common.BaseContext;
constructor(context: common.BaseContext) {
this.context = context;
this.udpSocket = socket.constructUDPSocketInstance(this.context);
}
// 启动UDP服务器
async startServer(port: number): Promise<boolean> {
try {
await this.udpSocket.bind({
address: '0.0.0.0',
port: port
});
console.info(`UDP服务器启动成功,端口: ${port}`);
this.setupMessageListener();
return true;
} catch (error) {
console.error(`UDP服务器启动失败: ${error.message}`);
return false;
}
}
// 监听消息
private setupMessageListener() {
this.udpSocket.on('message', async (value: socket.UDPSocketMessageInfo) => {
const message = String.fromCharCode.apply(null, value.message);
const remoteInfo = value.remoteInfo;
console.info(`收到来自${remoteInfo.address}:${remoteInfo.port}的消息: ${message}`);
// 回复消息
await this.sendResponse(`服务器已收到: ${message}`, remoteInfo);
});
this.udpSocket.on('error', (error: Error) => {
console.error(`UDP服务器错误: ${error.message}`);
});
}
// 发送响应
private async sendResponse(data: string, remoteInfo: socket.SocketRemoteInfo): Promise<void> {
try {
await this.udpSocket.send({
data: data,
address: {
address: remoteInfo.address,
port: remoteInfo.port
}
});
console.info(`响应发送成功到 ${remoteInfo.address}:${remoteInfo.port}`);
} catch (error) {
console.error(`发送响应失败: ${error.message}`);
}
}
// 停止服务器
async stopServer(): Promise<void> {
try {
await this.udpSocket.close();
console.info('UDP服务器已停止');
} catch (error) {
console.error(`停止UDP服务器失败: ${error.message}`);
}
}
}
4. 实战示例:聊天应用
4.1 聊天客户端实现
typescript
复制
下载
import socket from '@ohos.net.socket';
import common from '@ohos.app.ability.common';
import { BusinessError } from '@ohos.base';
class ChatClient {
private tcpClient: TCPClient;
private isConnected: boolean = false;
private messageCallback: (message: string) => void;
constructor(context: common.BaseContext) {
this.tcpClient = new TCPClient(context);
this.setupMessageHandlers();
}
// 连接到聊天服务器
async connectToServer(serverIP: string, port: number): Promise<boolean> {
this.isConnected = await this.tcpClient.connect(serverIP, port);
return this.isConnected;
}
// 设置消息处理器
private setupMessageHandlers() {
this.tcpClient.setupMessageListener((message: string) => {
if (this.messageCallback) {
this.messageCallback(message);
}
});
}
// 发送聊天消息
async sendMessage(message: string): Promise<boolean> {
if (!this.isConnected) {
console.error('未连接到服务器');
return false;
}
return await this.tcpClient.sendData(message);
}
// 设置消息回调
setMessageCallback(callback: (message: string) => void) {
this.messageCallback = callback;
}
// 断开连接
async disconnect(): Promise<void> {
await this.tcpClient.close();
this.isConnected = false;
}
}
4.2 UI界面实现
typescript
复制
下载
// ChatUI.ets
import { ChatClient } from './ChatClient';
import common from '@ohos.app.ability.common';
@Entry
@Component
struct ChatPage {
private chatClient: ChatClient = new ChatClient(getContext(this) as common.BaseContext);
@State messageList: string[] = [];
@State inputMessage: string = '';
@State serverIP: string = '192.168.1.100';
@State serverPort: number = 8080;
@State isConnected: boolean = false;
aboutToAppear() {
this.chatClient.setMessageCallback((message: string) => {
this.messageList.push(`服务器: ${message}`);
this.messageList = [...this.messageList];
});
}
build() {
Column({ space: 20 }) {
// 连接设置
Row({ space: 10 }) {
TextInput({ placeholder: '服务器IP', text: this.serverIP })
.onChange((value: string) => {
this.serverIP = value;
})
.layoutWeight(2)
TextInput({ placeholder: '端口', text: this.serverPort.toString() })
.onChange((value: string) => {
this.serverPort = parseInt(value) || 8080;
})
.layoutWeight(1)
Button(this.isConnected ? '断开' : '连接')
.onClick(() => {
if (this.isConnected) {
this.disconnect();
} else {
this.connect();
}
})
.layoutWeight(1)
}
.width('100%')
.padding(10)
// 消息显示区域
Scroll() {
Column() {
ForEach(this.messageList, (message: string, index: number) => {
Text(message)
.fontSize(16)
.textAlign(TextAlign.Start)
.backgroundColor(Color.White)
.borderRadius(10)
.padding(10)
.width('100%')
}, (message: string, index: number) => index.toString())
}
.width('100%')
.padding(10)
}
.layoutWeight(1)
.border({ width: 1, color: Color.Gray })
// 消息输入区域
Row({ space: 10 }) {
TextInput({ placeholder: '输入消息...', text: this.inputMessage })
.onChange((value: string) => {
this.inputMessage = value;
})
.layoutWeight(3)
Button('发送')
.onClick(() => {
this.sendMessage();
})
.layoutWeight(1)
}
.width('100%')
.padding(10)
}
.width('100%')
.height('100%')
.padding(20)
}
async connect() {
const success = await this.chatClient.connectToServer(this.serverIP, this.serverPort);
if (success) {
this.isConnected = true;
this.messageList.push('连接到服务器成功');
this.messageList = [...this.messageList];
} else {
this.messageList.push('连接服务器失败');
this.messageList = [...this.messageList];
}
}
async disconnect() {
await this.chatClient.disconnect();
this.isConnected = false;
this.messageList.push('已断开连接');
this.messageList = [...this.messageList];
}
async sendMessage() {
if (this.inputMessage.trim() === '') {
return;
}
const success = await this.chatClient.sendMessage(this.inputMessage);
if (success) {
this.messageList.push(`我: ${this.inputMessage}`);
this.messageList = [...this.messageList];
this.inputMessage = '';
} else {
this.messageList.push('发送失败');
this.messageList = [...this.messageList];
}
}
}
5. 错误处理与最佳实践
5.1 错误处理
typescript
复制
下载
class NetworkErrorHandler {
static handleSocketError(error: BusinessError): void {
const errorCode = error.code;
switch (errorCode) {
case 200:
console.error('网络不可用');
break;
case 201:
console.error('权限不足');
break;
case 202:
console.error('操作超时');
break;
case 203:
console.error('连接被拒绝');
break;
case 204:
console.error('连接重置');
break;
case 205:
console.error('连接关闭');
break;
default:
console.error(`网络错误: ${error.message}`);
}
}
static async retryOperation(
operation: () => Promise<boolean>,
maxRetries: number = 3
): Promise<boolean> {
for (let i = 0; i < maxRetries; i++) {
try {
const result = await operation();
if (result) {
return true;
}
} catch (error) {
console.error(`第${i + 1}次尝试失败: ${error.message}`);
if (i === maxRetries - 1) {
throw error;
}
// 指数退避
await this.delay(Math.pow(2, i) * 1000);
}
}
return false;
}
private static delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
5.2 性能优化建议
-
连接池管理:对于频繁的网络请求,使用连接池复用连接
-
数据压缩:传输大量数据时考虑使用压缩
-
心跳机制:保持长连接时实现心跳包
-
超时设置:合理设置连接和读取超时时间
-
异步处理:使用异步操作避免阻塞UI线程
6. 总结
本文详细介绍了在鸿蒙Next中使用Socket进行网络通信的完整流程,包括:
-
TCP和UDP协议的基本概念和区别
-
TCP客户端和服务器的完整实现
-
UDP客户端和服务器的完整实现
-
实战聊天应用示例
-
错误处理和性能优化建议
通过这些示例代码和最佳实践,您可以轻松地在鸿蒙Next应用中实现各种网络通信功能。记得在实际开发中根据具体需求调整代码,并始终关注网络安全和性能优化。
开启新对话
深度思考
联网搜索
内容由 AI 生成,请仔细甄别