#DAYU200体验官# Dayu200与Hi3861 TCP通信(JS) 原创 精华
Hello_Kun
发布于 2022-5-28 19:44
浏览
13收藏
@toc
0. 说明
OH系统版本:OpenHarmony3.1Release
IDE: 3.0.0.900
实现语言:JS
1. TCP JS接口
1.1 接口分析
参考地址:Socket连接
TCP通信流程:
Initial TCP ————> Bind IP ————> Connect Target IP ————> Send/Receive
- 初始化IP相关配置:
- 引用模块: import socket from '@ohos.net.socket'
- 添加权限:ohos.permission.INTERNET、ohos.permission.GET_WIFI_INFO
- 创建对象:let tcp = socket.constructTCPSocketInstance();
- 绑定IP与端口号
bind(address: NetAddress, callback: AsyncCallback<void>): void
绑定IP地址和端口,端口可以指定或由系统随机分配。使用callback方法作为异步方法。
需要权限:ohos.permission.INTERNET
系统能力:SystemCapability.Communication.NetStack
示例:
let tcp = socket.constructTCPSocketInstance();
tcp.bind({address: '192.168.xx.xxx', port: xxxx, family: 1}, err => {
if (err) {
console.log('bind fail');
return;
}
console.log('bind success');
})
- 连接目标IP
connect(options: TCPConnectOptions, callback: AsyncCallback<void>): void
连接到指定的IP地址和端口。使用callback方法作为异步方法。
需要权限:ohos.permission.INTERNET
系统能力:SystemCapability.Communication.NetStack
示例:
let tcp = socket.constructTCPSocketInstance();
tcp.connect({ address: {address: '192.168.xx.xxx', port: xxxx, family: 1} , timeout: 6000}, err => {
if (err) {
console.log('connect fail');
return;
}
console.log('connect success');
})
- 发送/接收数据
//发送数据
send(options: TCPSendOptions, callback: AsyncCallback<void>): void
通过TCPSocket连接发送数据。使用callback方式作为异步方法。
说明: connect方法调用成功后,才可调用此方法。
需要权限:ohos.permission.INTERNET
系统能力:SystemCapability.Communication.NetStack
示例:
tcpSend()
{
tcp.send({
data: this.app_msg,
}, err => {
if (err) {
console.log('send fail');
return;
}
});
},
//接收数据 并解析数据为String
on(type: ‘message’, callback: Callback<{message: ArrayBuffer, remoteInfo: SocketRemoteInfo}>): void
订阅TCPSocket连接的接收消息事件。使用callback方式作为异步方法。
系统能力:SystemCapability.Communication.NetStack
tcp.on('message', value => {
console.log("on message")
let buffer = value.message
let dataView = new DataView(buffer)
let str = ""
for (let i = 0;i < dataView.byteLength; ++i) {
str += String.fromCharCode(dataView.getUint8(i))
}
console.log("on connect received:" + str)
this.receive_data=str;
prompt.showToast({
message:str,
duration:1000
});
});
1.2 TPC send实现
按照上一节的流程,编写对应的JS程序即可。UI如下:
第一个按钮用于绑定IP,并设置订阅TCPSocket相关的订阅事件
tcpClient()
{
// 订阅TCPSocket相关的订阅事件
tcp.on('message', value => {
console.log("on message")
let buffer = value.message
let dataView = new DataView(buffer)
let str = ""
for (let i = 0;i < dataView.byteLength; ++i) {
str += String.fromCharCode(dataView.getUint8(i))
}
console.log("on connect received:" + str)
this.receive_data=str;
prompt.showToast({
message:str,
duration:1000
});
});
tcp.on('connect', () => {
console.log("on connect")
});
tcp.on('close', () => {
console.log("on close")
});
// 绑定IP地址和端口。
let bindAddress = {
address: wifi.getIpInfo().ipAddress,
port: 1234,
family: 1
};
tcp.bind(bindAddress, err => {
if (err) {
console.log('bind fail');
return;
}
console.log('bind success');
prompt.showToast({
message:"bind success",
})
});
},
第二个按钮用于连接Hi3861:
tcpConnect()
{
prompt.showToast({
message:'wifiAddr'+wifi.isConnected()+wifi.getIpInfo().ipAddress,
});
// let promise = tcp.connect({ address: {address:'192.168.137.92', port: 8888, family: 1} , timeout: 6000});
// promise.then(() => {
// console.log('connect success')
// prompt.showToast({
// message:"connect success",
// });
// }).catch(err => {
// prompt.showToast({
// message:"connect fail",
// });
// console.log('connect fail');
// });
tcp.connect({ address: {address: '192.168.137.92', port: 8888, family: 1} , timeout: 6000}, err => {
if (err) {
console.log('connect fail');
prompt.showToast({
message:"connect fail",
});
return;
}
console.log('connect success');
prompt.showToast({
message:"connect success",
});
})
},
第三个按钮实现发送数据:
tcpSend()
{
tcp.send({
data: this.app_msg,
}, err => {
if (err) {
console.log('send fail');
prompt.showToast({
message:"send fail",
});
return;
}
prompt.showToast({
message:"send successful"
})
});
},
2. Hi3861 TCP
2.1 初始化
参考小熊派开发板TCP server案例。主要任务是开启wifi,获取周围wifi列表。
#define SELECT_WLAN_PORT "wlan0"
int WifiConnect(const char *ssid, const char *psk)
{
WifiScanInfo *info = NULL;
unsigned int size = WIFI_SCAN_HOTSPOT_LIMIT;
static struct netif *g_lwip_netif = NULL;
osDelay(200);
printf("<--System Init-->\r\n");
//初始化WIFI
WiFiInit();
//使能WIFI
if (EnableWifi() != WIFI_SUCCESS)
{
printf("EnableWifi failed, error = %d\r\n", error);
return -1;
}
//判断WIFI是否激活
if (IsWifiActive() == 0)
{
printf("Wifi station is not actived.\r\n");
return -1;
}
//分配空间,保存WiFi信息
info = malloc(sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT);
if (info == NULL)
{
return -1;
}
//轮询查找WiFi列表
do{
//重置标志位
ssid_count = 0;
g_staScanSuccess = 0;
//开始扫描
Scan();
//等待扫描结果
WaitSacnResult();
//获取扫描列表
error = GetScanInfoList(info, &size);
}while(g_staScanSuccess != 1);
//连接指定的WiFi热点
for(uint8_t i = 0; i < ssid_count; i++)
{
if (strcmp(ssid, info[i].ssid) == 0)
{
int result;
printf("Select:%3d wireless, Waiting...\r\n", i+1);
//拷贝要连接的热点信息
WifiDeviceConfig select_ap_config = {0};
strcpy(select_ap_config.ssid, info[i].ssid);
strcpy(select_ap_config.preSharedKey, psk);
select_ap_config.securityType = SELECT_WIFI_SECURITYTYPE;
if (AddDeviceConfig(&select_ap_config, &result) == WIFI_SUCCESS)
{
if (ConnectTo(result) == WIFI_SUCCESS && WaitConnectResult() == 1)
{
printf("WiFi connect succeed!\r\n");
g_lwip_netif = netifapi_netif_find(SELECT_WLAN_PORT);
break;
}
}
}
if(i == ssid_count-1)
{
printf("ERROR: No wifi as expected\r\n");
while(1) osDelay(100);
}
}
//启动DHCP
if (g_lwip_netif)
{
dhcp_start(g_lwip_netif);
printf("begain to dhcp\r\n");
}
//等待DHCP
for(;;)
{
if(dhcp_is_bound(g_lwip_netif) == ERR_OK)
{
printf("<-- DHCP state:OK -->\r\n");
//打印获取到的IP信息
netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);
break;
}
printf("<-- DHCP state:Inprogress -->\r\n");
osDelay(100);
}
osDelay(100);
return 0;
}
2.2 作为TCP Server
连接指定wifi,创建socket server,监听指定IP 端口。
char *buf = "Hello! I'm BearPi-HM_Nano TCP Server!";
static void TCPServerTask(void)
{
//服务端地址信息
struct sockaddr_in server_sock;
//客户端地址信息
struct sockaddr_in client_sock;
int sin_size;
struct sockaddr_in *cli_addr;
//连接Wifi
WifiConnect("r1", "88888889");
//创建socket
if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket is error\r\n");
exit(1);
}
bzero(&server_sock, sizeof(server_sock));
server_sock.sin_family = AF_INET;
server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
server_sock.sin_port = htons(_PROT_);
//调用bind函数绑定socket和地址
if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
{
perror("bind is error\r\n");
exit(1);
}
//调用listen函数监听(指定port监听)
if (listen(sock_fd, TCP_BACKLOG) == -1)
{
perror("listen is error\r\n");
exit(1);
}
printf("start accept\n");
//调用accept函数从队列中
while (1)
{
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sock_fd, (struct sockaddr *)&client_sock, (socklen_t *)&sin_size)) == -1)
{
perror("accept");
continue;
}
cli_addr = malloc(sizeof(struct sockaddr));
printf("accept addr\r\n");
if (cli_addr != NULL)
{
memcpy(cli_addr, &client_sock, sizeof(struct sockaddr));
}
//处理目标
ssize_t ret;
while (1)
{
if ((ret = recv(new_fd, recvbuf, sizeof(recvbuf), 0)) == -1)
{
printf("recv error \r\n");
}
printf("recv :%s\r\n", recvbuf);
sleep(2);
if ((ret = send(new_fd, buf, strlen(buf) + 1, 0)) == -1)
{
perror("send : ");
}
sleep(2);
}
close(new_fd);
}
}
3. 测试
将Hi3861、Dayu200都连接到同一个wifi下,事先匹配好IP地址和端口:
连接后Hi3861只要接收到数据就会返回一段字符串,Hi3861接收到的数据可以使用串口查看:
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-5-30 10:25:32修改
赞
11
收藏 13
回复
相关推荐
非常实用的演示,学习了