ArkTs中的wbSocket

1、**配置网络权限:**根据网页2和6,需要在module.json5中添加INTERNET权限。这是必要的前提条件。
2、**导入模块:**使用来自@kit.NetworkKit的webSocket模块,所以正确的导入应该是import webSocket from ‘@ohos.net.webSocket’或者类似,需要确认具体路径。网页6的代码示例显示导入的是’@ohos.net.webSocket’,或者@kit.NetworkKit,可能版本不同,需要统一说明。
3、**创建WebSocket实例:**使用createWebSocket方法,如let ws = webSocket.createWebSocket();
4、**连接服务器:**调用connect方法,传入服务器地址,可能有回调处理错误。
5、**事件处理:**订阅open、message、close、error事件,处理各自的回调函数。例如,在open事件中发送初始消息,在message中处理接收的数据,close时进行清理,error时处理异常。
6、**发送消息:**通过send方法发送文本或二进制数据,注意异步回调处理可能的错误。
7、**关闭连接:**调用close方法,确保资源释放。

在ArkTS中创建WebSocket连接主要涉及以下步骤和关键接口,结合HarmonyOS官方文档及开发者实践经验,具体流程如下:

ArkTs中的wbSocket

一、配置网络权限

在module.json5文件中添加网络权限声明:

"requestPermissions": [
  {"name": "ohos.permission.INTERNET"}

二、导入WebSocket模块

使用ArkTS提供的原生API,需从@ohos.net.webSocket模块导入相关功能:

import webSocket from '@ohos.net.webSocket';

三、创建WebSocket实例

通过createWebSocket()方法初始化连接对象:

let ws = webSocket.createWebSocket();

四、建立连接

调用connect()方法并指定服务器地址(支持ws://或wss://协议):

const serverUrl = 'ws://your-server-address:port';
ws.connect(serverUrl, (err: BusinessError, value: boolean) => {
if (!err) {
    console.log('连接成功');
else {
    console.error('连接失败:', JSON.stringify(err));
});

五、事件监听与处理

需订阅以下核心事件实现双向通信:
open事件

连接成功时触发,通常用于发送初始消息:

     ws.on('open', (err: BusinessError, value: Object) => {
     if (!err) {
       ws.send('Hello Server', (sendErr) => { / 处理发送结果 / });
     });

message事件

接收服务器消息,支持文本和二进制数据:

     ws.on('message', (err: BusinessError, value: string | ArrayBuffer) => {
     if (!err) {
       console.log('收到消息:', value);
     });

close事件

连接关闭时触发,可获取关闭状态码和原因:
ws.on(‘close’, (err: BusinessError, value: webSocket.CloseResult) => {
console.log(连接关闭,代码: {value.code}, 原因: {value.reason});
});

error事件

处理连接或通信中的异常:

   ws.on('error', (err: BusinessError) => {
     console.error('发生错误:', JSON.stringify(err));
   });

六、发送消息

通过send()方法发送数据(支持文本或ArrayBuffer):

ws.send('Hello World', (err: BusinessError) => {
  if (!err) {
    console.log('消息发送成功');
  }
});

七、关闭连接

调用close()主动断开连接:

ws.close((err: BusinessError) => {
  if (!err) {
    console.log('连接已关闭');
  }
});

注意事项

协议安全性:敏感数据传输应使用wss://协议加密。

错误恢复:需处理网络中断等异常,可加入自动重连机制。

性能优化:高频通信场景建议采用消息队列或异步处理防止阻塞。

资源释放:页面销毁时需取消事件监听并关闭连接。

完整示例代码

import webSocket from '@ohos.net.webSocket';

let ws = webSocket.createWebSocket();
ws.on('open', (err, value) => {
  if (!err) {
    ws.send('Hello Server', (sendErr) => { / 处理发送 / });
});

ws.on('message', (err, value) => {
  if (value === 'bye') ws.close(); // 服务器发送bye时关闭连接
});

ws.connect('ws://your-server:8080', (err) => { / 处理连接结果 / });

以上步骤结合了HarmonyOS官方接口规范及开发者实践经验,适用于HarmonyOS NEXT环境下的实时通信场景(如聊天、实时数据监控等)。具体实现需根据服务器协议调整参数。

每一个ws.on是否都是一个独立线程,用于监听服务器信息

在 ArkTS(HarmonyOS NEXT)的 WebSocket 实现中,**所有 ws.on 事件监听器均运行在主线程(ArkTS 引擎主线程)中,不会创建独立线程。**以下是具体分析:

1、ArkTS 的单线程模型

**主线程特性:**ArkTS 的 JavaScript 运行环境基于单线程事件循环机制,所有同步代码、异步回调(如 Promise、setTimeout)及 WebSocket 事件监听均在主线程中执行。

**事件队列机制:**通过事件队列(宏任务队列和微任务队列)处理异步操作,如 onopen、onmessage 等回调函数会被推入队列,由主线程按顺序执行。

2、WebSocket 事件监听机制

**非阻塞监听:**ws.on 方法仅注册回调函数,不会阻塞主线程。当服务器消息到达时,底层网络库(如 libuv)会将消息封装为事件,插入主线程的事件队列,最终由主线程触发对应的回调。

事件类型示例:

  // 以下所有回调均在同一线程(主线程)执行
  ws.on('open', () => { / 连接成功回调 / });
  ws.on('message', (data) => { / 接收消息回调 / });
  ws.on('close', () => { / 连接关闭回调 / });

3、多线程与并发的实现方式

虽然事件监听本身不创建线程,但 ArkTS 提供了两种多线程方案处理耗时操作,避免阻塞主线程:
(1)Worker 线程

独立于主线程运行,需手动创建和管理。

通过消息传递与主线程通信(序列化数据,最大 16MB)。

适用场景:长时间 CPU 密集型任务(如复杂计算)。
(2)TaskPool 任务池

系统管理的线程池,支持任务优先级和负载均衡。

适用场景:短期耗时操作(如批量数据处理)。

4、性能与注意事项

**避免主线程阻塞:**若在 onmessage 回调中执行耗时操作(如循环计算),会导致 UI 卡顿甚至应用崩溃(超过 6 秒触发 APP_INPUT_BLOCK 错误)。

**正确做法:**将耗时逻辑移至 Worker 或 TaskPool:

  // 示例:在 Worker 中处理消息
  const worker = new worker.ThreadWorker('workers/MessageHandler.ets');
  ws.on('message', (data) => {
    worker.postMessage(data); // 将消息转发给 Worker
  });

总结

**ws.on 监听器:**均在主线程执行,依赖事件队列实现异步非阻塞。

**多线程需求:**需通过 Worker 或 TaskPool 显式创建,与 WebSocket 事件监听无关。

**设计建议:**根据业务场景选择并发模型,避免主线程阻塞导致体验问题。

linux中C语言版本的socket连接步骤

以下是 Linux 环境下 C 语言版本的 Socket 连接步骤详解,结合多篇技术文档和实践案例整理:

一、服务端实现步骤

1、创建 Socket

int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
    perror("socket creation failed");
    exit(EXIT_FAILURE);
}

参数说明:

AF_INET 表示 IPv4 协议;
SOCK_STREAM 表示 TCP 协议(若使用 UDP 则为 SOCK_DGRAM)。
2、配置地址结构体

struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有网卡
server_addr.sin_port = htons(8080);             // 设置端口号

关键函数:

htons() 将主机字节序转换为网络字节序(16 位);
htonl() 用于 32 位数据转换。
3、绑定地址

if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
    perror("bind failed");
    exit(EXIT_FAILURE);
}

**作用:**将 Socket 与 IP 地址和端口号关联。
4、监听连接

if (listen(server_fd, 5) == -1) { // 最大连接队列长度设为5
    perror("listen failed");
    exit(EXIT_FAILURE);
}

5、接受客户端连接

struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len);
if (client_fd == -1) {
    perror("accept failed");
    exit(EXIT_FAILURE);
}

**阻塞特性:**accept() 会阻塞直到有客户端连接。
6、数据收发

char buffer[1024];
ssize_t bytes_received = recv(client_fd, buffer, sizeof(buffer), 0);
if (bytes_received == -1) {
    perror("recv failed");
}
const char* response = "Message received";

send(client_fd, response, strlen(response), 0);

7、关闭连接

close(client_fd);
close(server_fd);

二、客户端实现步骤

1、创建 Socket

int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
    perror("socket creation failed");
    exit(EXIT_FAILURE);
}

2、配置服务器地址

struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr); // 转换IP地址

3、连接服务器

if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
    perror("connect failed");
    exit(EXIT_FAILURE);
}

4、数据收发

const char* message = "Hello Server";
send(sock, message, strlen(message), 0);

char buffer[1024];
recv(sock, buffer, sizeof(buffer), 0);
printf("Server response: %s\n", buffer);

5、关闭连接

close(sock);

三、关键注意事项

错误处理

每个系统调用后需检查返回值(如 socket() 返回 -1 表示失败),使用 perror() 或 strerror(errno) 输出错误信息。
字节序转换

必须使用 htons() 和 htonl() 转换端口和 IP 地址,避免因主机与网络字节序不同导致通信失败。
多线程优化

服务端可通过 pthread_create() 为每个客户端创建独立线程(示例代码见网页1),避免阻塞主线程。
协议选择

TCP:可靠传输,需三次握手(SOCK_STREAM)。

UDP:无连接传输(SOCK_DGRAM),需改用 sendto() 和 recvfrom()。

四、完整示例代码

服务端代码(简化版)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(client_addr);
    char buffer[BUFFER_SIZE] = {0};

    // 1. 创建Socket
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 2. 配置地址结构体
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY; // 绑定所有网卡[3](@ref)
    server_addr.sin_port = htons(PORT);       // 端口转换字节序[1](@ref)

    // 3. 绑定地址
    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
        perror("Bind failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // 4. 开始监听
    if (listen(server_fd, 5) == -1) { // 最大队列长度5[6](@ref)
        perror("Listen failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    printf("Server listening on port %d...\n", PORT);

    // 5. 接受客户端连接
    if ((client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addr_len)) == -1) {
        perror("Accept failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    printf("Client connected from %s:%d\n", 
           inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

    // 6. 数据收发
    ssize_t bytes_read = read(client_fd, buffer, BUFFER_SIZE);
    printf("Received: %s\n", buffer);
    
    const char* response = "Message received";
    send(client_fd, response, strlen(response), 0);

    // 7. 关闭连接
    close(client_fd);
    close(server_fd);
    return 0;
}

客户端代码(简化版)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define PORT 8080
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024

int main() {
    int sock;
    struct sockaddr_in serv_addr;
    char buffer[BUFFER_SIZE] = {0};

    // 1. 创建Socket
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 2. 配置服务器地址
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0) { // IP转换[7](@ref)
        perror("Invalid address");
        close(sock);
        exit(EXIT_FAILURE);
    }

    // 3. 连接服务器
    if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
        perror("Connection failed");
        close(sock);
        exit(EXIT_FAILURE);
    }
    printf("Connected to server\n");

    // 4. 发送数据
    const char* message = "Hello from client";
    send(sock, message, strlen(message), 0);
    printf("Message sent\n");

    // 5. 接收响应
    read(sock, buffer, BUFFER_SIZE);
    printf("Server response: %s\n", buffer);

    // 6. 关闭连接
    close(sock);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值