【HarmonyOS NEXT】鸿蒙Socket 连接

简介

Socket 连接主要是通过 Socket 进行数据传输,支持 TCP/UDP/Multicast/TLS 协议。

基本概念

  • Socket:套接字,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。
  • TCP:传输控制协议(Transmission Control Protocol)。是一种面向连接的、可靠的、基于字节流的传输层通信协议。
  • UDP:用户数据报协议(User Datagram Protocol)。是一个简单的面向消息的传输层,不需要连接。
  • Multicast:多播,基于UDP的一种通信模式,用于实现组内所有设备之间广播形式的通信。
  • LocalSocket:本地套接字,IPC(Inter-Process Communication)进程间通信的一种,实现设备内进程之间相互通信,无需网络。
  • TLS:安全传输层协议(Transport Layer Security)。用于在两个通信应用程序之间提供保密性和数据完整性。

场景介绍

应用通过 Socket 进行数据传输,支持 TCP/UDP/Multicast/TLS 协议。主要场景有:

  • 应用通过 TCP/UDP Socket进行数据传输
  • 应用通过 TCP Socket Server 进行数据传输
  • 应用通过 Multicast Socket 进行数据传输
  • 应用通过 Local Socket进行数据传输
  • 应用通过 Local Socket Server 进行数据传输
  • 应用通过 TLS Socket 进行加密数据传输
  • 应用通过 TLS Socket Server 进行加密数据传输

接口说明

Socket 连接主要由 socket 模块提供。具体接口说明如下表。

接口名描述
constructUDPSocketInstance()创建一个 UDPSocket 对象。
constructTCPSocketInstance()创建一个 TCPSocket 对象。
constructTCPSocketServerInstance()创建一个 TCPSocketServer 对象。
constructMulticastSocketInstance()创建一个 MulticastSocket 对象。
constructLocalSocketInstance()创建一个 LocalSocket 对象。
constructLocalSocketServerInstance()创建一个 LocalSocketServer 对象。
listen()绑定、监听并启动服务,接收客户端的连接请求。(仅 TCP/LocalSocket 支持)。
bind()绑定 IP 地址和端口,或是绑定本地套接字路径。
send()发送数据。
close()关闭连接。
getState()获取 Socket 状态。
connect()连接到指定的 IP 地址和端口,或是连接到本地套接字(仅 TCP/LocalSocket 支持)。
getRemoteAddress()获取对端 Socket 地址(仅 TCP 支持,需要先调用 connect 方法)。
setExtraOptions()设置 Socket 连接的其他属性。
getExtraOptions()获取 Socket 连接的其他属性(仅 LocalSocket 支持)。
addMembership()加入到指定的多播组 IP 中 (仅 Multicast 支持)。
dropMembership()从指定的多播组 IP 中退出 (仅 Multicast 支持)。
setMulticastTTL()设置数据传输跳数 TTL (仅 Multicast 支持)。
getMulticastTTL()获取数据传输跳数 TTL (仅 Multicast 支持)。
setLoopbackMode()设置回环模式,允许主机在本地循环接收自己发送的多播数据包 (仅 Multicast 支持)。
getLoopbackMode()获取回环模式开启或关闭的状态 (仅 Multicast 支持)。
on(type: 'message')订阅 Socket 连接的接收消息事件。
off(type: 'message')取消订阅 Socket 连接的接收消息事件。
on(type: 'close')订阅 Socket 连接的关闭事件。
off(type: 'close')取消订阅 Socket 连接的关闭事件。
on(type: 'error')订阅 Socket 连接的 Error 事件。
off(type: 'error')取消订阅 Socket 连接的 Error 事件。
on(type: 'listening')订阅 UDPSocket 连接的数据包消息事件(仅 UDP 支持)。
off(type: 'listening')取消订阅 UDPSocket 连接的数据包消息事件(仅 UDP 支持)。
on(type: 'connect')订阅 Socket 的连接事件(仅 TCP/LocalSocket 支持)。
off(type: 'connect')取消订阅 Socket 的连接事件(仅 TCP/LocalSocket 支持)。

TLS Socket 连接主要由 tls_socket 模块提供。具体接口说明如下表。

接口名功能描述
constructTLSSocketInstance()创建一个 TLSSocket 对象。
bind()绑定 IP 地址和端口号。
close(type: 'error')关闭连接。
connect()连接到指定的 IP 地址和端口。
getCertificate()返回表示本地证书的对象。
getCipherSuite()返回包含协商的密码套件信息的列表。
getProtocol()返回包含当前连接协商的 SSL/TLS 协议版本的字符串。
getRemoteAddress()获取 TLSSocket 连接的对端地址。
getRemoteCertificate()返回表示对等证书的对象。
getSignatureAlgorithms()在服务器和客户端之间共享的签名算法列表,按优先级降序排列。
getState()获取 TLSSocket 连接的状态。
off(type: 'close')取消订阅 TLSSocket 连接的关闭事件。
off(type: 'error')取消订阅 TLSSocket 连接的 Error 事件。
off(type: 'message')取消订阅 TLSSocket 连接的接收消息事件。
on(type: 'close')订阅 TLSSocket 连接的关闭事件。
on(type: 'error')订阅 TLSSocket 连接的 Error 事件。
on(type: 'message')订阅 TLSSocket 连接的接收消息事件。
send()发送数据。
setExtraOptions()设置 TLSSocket 连接的其他属性。

应用 TCP/UDP 协议进行通信

UDP 与 TCP 流程大体类似,下面以 TCP 为例:

  1. import 需要的 socket 模块。

  2. 创建一个 TCPSocket 连接,返回一个 TCPSocket 对象。

  3. (可选)订阅 TCPSocket 相关的订阅事件。

  4. 绑定 IP 地址和端口,端口可以指定或由系统随机分配。

  5. 连接到指定的 IP 地址和端口。

  6. 发送数据。

  7. Socket 连接使用完毕后,主动关闭。

import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

class SocketInfo {
  message: ArrayBuffer = new ArrayBuffer(1);
  remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}
// 创建一个TCPSocket连接,返回一个TCPSocket对象。
let tcp: socket.TCPSocket = socket.constructTCPSocketInstance();
tcp.on('message', (value: SocketInfo) => {
  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);
});
tcp.on('connect', () => {
  console.log("on connect");
});
tcp.on('close', () => {
  console.log("on close");
});

// 绑定本地IP地址和端口。
let ipAddress : socket.NetAddress = {} as socket.NetAddress;
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 1234;
tcp.bind(ipAddress, (err: BusinessError) => {
  if (err) {
    console.log('bind fail');
    return;
  }
  console.log('bind success');

  // 连接到指定的IP地址和端口。
  ipAddress.address = "192.168.xxx.xxx";
  ipAddress.port = 5678;

  let tcpConnect : socket.TCPConnectOptions = {} as socket.TCPConnectOptions;
  tcpConnect.address = ipAddress;
  tcpConnect.timeout = 6000;

  tcp.connect(tcpConnect).then(() => {
    console.log('connect success');
    let tcpSendOptions: socket.TCPSendOptions = {
      data: 'Hello, server!'
    }
    tcp.send(tcpSendOptions).then(() => {
      console.log('send success');
    }).catch((err: BusinessError) => {
      console.log('send fail');
    });
  }).catch((err: BusinessError) => {
    console.log('connect fail');
  });
});

// 连接使用完毕后,主动关闭。取消相关事件的订阅。
setTimeout(() => {
  tcp.close().then(() => {
    console.log('close success');
  }).catch((err: BusinessError) => {
    console.log('close fail');
  });
  tcp.off('message');
  tcp.off('connect');
  tcp.off('close');
}, 30 * 1000);

应用通过 TCP Socket Server 进行数据传输

开发步骤

服务端 TCP Socket 流程:

  1. import 需要的 socket 模块。
  2. 创建一个 TCPSocketServer 连接,返回一个 TCPSocketServer 对象。
  3. 绑定本地 IP 地址和端口,监听并接受与此套接字建立的客户端 TCPSocket 连接。
  4. 订阅 TCPSocketServer 的 connect 事件,用于监听客户端的连接状态。
  5. 客户端与服务端建立连接后,返回一个 TCPSocketConnection 对象,用于与客户端通信。
  6. 订阅 TCPSocketConnection 相关的事件,通过 TCPSocketConnection 向客户端发送数据。
  7. 主动关闭与客户端的连接。
  8. 取消 TCPSocketConnection 和 TCPSocketServer 相关事件的订阅。
import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

// 创建一个TCPSocketServer连接,返回一个TCPSocketServer对象。
let tcpServer: socket.TCPSocketServer = socket.constructTCPSocketServerInstance();
// 绑定本地IP地址和端口,进行监听

let ipAddress : socket.NetAddress = {} as socket.NetAddress;
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 4651;
tcpServer.listen(ipAddress).then(() => {
  console.log('listen success');
}).catch((err: BusinessError) => {
  console.log('listen fail');
});

class SocketInfo {
  message: ArrayBuffer = new ArrayBuffer(1);
  remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}
// 订阅TCPSocketServer的connect事件
tcpServer.on("connect", (client: socket.TCPSocketConnection) => {
  // 订阅TCPSocketConnection相关的事件
  client.on("close", () => {
    console.log("on close success");
  });
  client.on("message", (value: SocketInfo) => {
    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("received message--:" + str);
    console.log("received address--:" + value.remoteInfo.address);
    console.log("received family--:" + value.remoteInfo.family);
    console.log("received port--:" + value.remoteInfo.port);
    console.log("received size--:" + value.remoteInfo.size);
  });

  // 向客户端发送数据
  let tcpSendOptions : socket.TCPSendOptions = {} as socket.TCPSendOptions;
  tcpSendOptions.data = 'Hello, client!';
  client.send(tcpSendOptions).then(() => {
    console.log('send success');
  }).catch((err: Object) => {
    console.error('send fail: ' + JSON.stringify(err));
  });

  // 关闭与客户端的连接
  client.close().then(() => {
    console.log('close success');
  }).catch((err: BusinessError) => {
    console.log('close fail');
  });

  // 取消TCPSocketConnection相关的事件订阅
  setTimeout(() => {
    client.off("message");
    client.off("close");
  }, 10 * 1000);
});

// 取消TCPSocketServer相关的事件订阅
setTimeout(() => {
  tcpServer.off("connect");
}, 30 * 1000);

应用通过 Multicast Socket 进行数据传输

开发步骤

  1. import 需要的 socket 模块。

  2. 创建 multicastSocket 多播对象。

  3. 指定多播 IP 与端口,加入多播组。

  4. 开启消息 message 监听。

  5. 发送数据,数据以广播的形式传输,同一多播组中已经开启消息 message 监听的多播对象都会接收到数据。

  6. 关闭 message 消息的监听。

  7. 退出多播组。

import { socket } from '@kit.NetworkKit';

// 创建Multicast对象
let multicast: socket.MulticastSocket = socket.constructMulticastSocketInstance();

let addr : socket.NetAddress = {
  address: '239.255.0.1',
  port: 32123,
  family: 1
}

// 加入多播组
multicast.addMembership(addr).then(() => {
  console.log('addMembership success');
}).catch((err: Object) => {
  console.log('addMembership fail');
});

// 开启监听消息数据,将接收到的ArrayBuffer类型数据转换为String
class SocketInfo {
  message: ArrayBuffer = new ArrayBuffer(1);
  remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}
multicast.on('message', (data: SocketInfo) => {
  console.info('接收的数据: ' + JSON.stringify(data))
  const uintArray = new Uint8Array(data.message)
  let str = ''
  for (let i = 0; i < uintArray.length; ++i) {
    str += String.fromCharCode(uintArray[i])
  }
  console.info(str)
})

// 发送数据
multicast.send({ data:'Hello12345', address: addr }).then(() => {
  console.log('send success');
}).catch((err: Object) => {
  console.log('send fail, ' + JSON.stringify(err));
});

// 关闭消息的监听
multicast.off('message')

// 退出多播组
multicast.dropMembership(addr).then(() => {
  console.log('drop membership success');
}).catch((err: Object) => {
  console.log('drop membership fail');
});

应用通过 LocalSocket 进行数据传输

开发步骤:

  1. import 需要的 socket 模块。

  2. 使用 constructLocalSocketInstance 接口,创建一个 LocalSocket 客户端对象。

  3. 注册 LocalSocket 的消息(message)事件,以及一些其它事件(可选)。

  4. 连接到指定的本地套接字文件路径。

  5. 发送数据。

  6. Socket 连接使用完毕后,取消事件的注册,并关闭套接字。

import { socket } from '@kit.NetworkKit';

// 创建一个LocalSocket连接,返回一个LocalSocket对象。
let client: socket.LocalSocket = socket.constructLocalSocketInstance();
client.on('message', (value: socket.LocalSocketMessageInfo) => {
  const uintArray = new Uint8Array(value.message)
  let messageView = '';
  for (let i = 0; i < uintArray.length; i++) {
    messageView += String.fromCharCode(uintArray[i]);
  }
  console.log('total receive: ' + JSON.stringify(value));
  console.log('message information: ' + messageView);
});
client.on('connect', () => {
  console.log("on connect");
});
client.on('close', () => {
  console.log("on close");
});

// 传入指定的本地套接字路径,连接服务端。
let sandboxPath: string = getContext(this).filesDir + '/testSocket'
let localAddress : socket.LocalAddress = {
  address: sandboxPath
}
let connectOpt: socket.LocalConnectOptions = {
  address: localAddress,
  timeout: 6000
}
let sendOpt: socket.LocalSendOptions = {
  data: 'Hello world!'
}
client.connect(connectOpt).then(() => {
  console.log('connect success')
  client.send(sendOpt).then(() => {
  console.log('send success')
  }).catch((err: Object) => {
    console.log('send failed: ' + JSON.stringify(err))
  })
}).catch((err: Object) => {
  console.log('connect fail: ' + JSON.stringify(err));
});

// 当不需要再连接服务端,需要断开且取消事件的监听时
client.off('message');
client.off('connect');
client.off('close');
client.close().then(() => {
  console.log('close client success')
}).catch((err: Object) => {
  console.log('close client err: ' + JSON.stringify(err))
})

应用通过 Local Socket Server 进行数据传输

开发步骤

服务端 LocalSocket Server 流程:

  1. import 需要的 socket 模块。

  2. 使用 constructLocalSocketServerInstance 接口,创建一个 LocalSocketServer 服务端对象。

  3. 启动服务,绑定本地套接字路径,创建出本地套接字文件,监听客户端的连接请求。

  4. 注册 LocalSocket 的客户端连接(connect)事件,以及一些其它事件(可选)。

  5. 在客户端连接上来时,通过连接事件的回调函数,获取连接会话对象。

  6. 给会话对象 LocalSocketConnection 注册消息(message)事件,以及一些其它事件(可选)。

  7. 通过会话对象主动向客户端发送消息。

  8. 结束与客户端的通信,主动断开与客户端的连接。

  9. 取消 LocalSocketConnection 和 LocalSocketServer 相关事件的订阅。

import { socket } from '@kit.NetworkKit';

// 创建一个LocalSocketServer连接,返回一个LocalSocketServer对象。
let server: socket.LocalSocketServer = socket.constructLocalSocketServerInstance();
// 创建并绑定本地套接字文件testSocket,进行监听
let sandboxPath: string = getContext(this).filesDir + '/testSocket'
let listenAddr: socket.LocalAddress = {
  address: sandboxPath
}
server.listen(listenAddr).then(() => {
  console.log("listen success");
}).catch((err: Object) => {
  console.log("listen fail: " + JSON.stringify(err));
});

// 订阅LocalSocketServer的connect事件
server.on('connect', (connection: socket.LocalSocketConnection) => {
  // 订阅LocalSocketConnection相关的事件
  connection.on('error', (err: Object) => {
    console.log("on error success");
  });
  connection.on('message', (value: socket.LocalSocketMessageInfo) => {
    const uintArray = new Uint8Array(value.message);
    let messageView = '';
    for (let i = 0; i < uintArray.length; i++) {
      messageView += String.fromCharCode(uintArray[i]);
    }
    console.log('total: ' + JSON.stringify(value));
    console.log('message information: ' + messageView);
  });

  connection.on('error', (err: Object) => {
    console.log("err:" + JSON.stringify(err));
  })

  // 向客户端发送数据
  let sendOpt : socket.LocalSendOptions = {
    data: 'Hello world!'
  };
  connection.send(sendOpt).then(() => {
    console.log('send success');
  }).catch((err: Object) => {
    console.log('send failed: ' + JSON.stringify(err));
  })

  // 关闭与客户端的连接
  connection.close().then(() => {
    console.log('close success');
  }).catch((err: Object) => {
    console.log('close failed: ' + JSON.stringify(err));
  });

  // 取消LocalSocketConnection相关的事件订阅
  connection.off('message');
  connection.off('error');
});

// 取消LocalSocketServer相关的事件订阅
server.off('connect');
server.off('error');

应用通过 TLS Socket 进行加密数据传输

开发步骤

客户端 TLS Socket 流程:

  1. import 需要的 socket 模块。

  2. 绑定服务器 IP 和端口号。

  3. 双向认证上传客户端 CA 证书及数字证书;单向认证上传客户端 CA 证书。

  4. 创建一个 TLSSocket 连接,返回一个 TLSSocket 对象。

  5. (可选)订阅 TLSSocket 相关的订阅事件。

  6. 发送数据。

  7. TLSSocket 连接使用完毕后,主动关闭。

import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

class SocketInfo {
  message: ArrayBuffer = new ArrayBuffer(1);
  remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}
// 创建一个(双向认证)TLS Socket连接,返回一个TLS Socket对象。
let tlsTwoWay: socket.TLSSocket = socket.constructTLSSocketInstance();
// 订阅TLS Socket相关的订阅事件
tlsTwoWay.on('message', (value: SocketInfo) => {
  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);
});
tlsTwoWay.on('connect', () => {
  console.log("on connect");
});
tlsTwoWay.on('close', () => {
  console.log("on close");
});

// 绑定本地IP地址和端口。
let ipAddress : socket.NetAddress = {} as socket.NetAddress;
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 4512;
tlsTwoWay.bind(ipAddress, (err: BusinessError) => {
  if (err) {
    console.log('bind fail');
    return;
  }
  console.log('bind success');
});

ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 1234;

let tlsSecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions;
tlsSecureOption.key = "xxxx";
tlsSecureOption.cert = "xxxx";
tlsSecureOption.ca = ["xxxx"];
tlsSecureOption.password = "xxxx";
tlsSecureOption.protocols = [socket.Protocol.TLSv12];
tlsSecureOption.useRemoteCipherPrefer = true;
tlsSecureOption.signatureAlgorithms = "rsa_pss_rsae_sha256:ECDSA+SHA256";
tlsSecureOption.cipherSuite = "AES256-SHA256";

let tlsTwoWayConnectOption : socket.TLSConnectOptions = {} as socket.TLSConnectOptions;
tlsSecureOption.key = "xxxx";
tlsTwoWayConnectOption.address = ipAddress;
tlsTwoWayConnectOption.secureOptions = tlsSecureOption;
tlsTwoWayConnectOption.ALPNProtocols = ["spdy/1", "http/1.1"];

// 建立连接
tlsTwoWay.connect(tlsTwoWayConnectOption).then(() => {
  console.log("connect successfully");
}).catch((err: BusinessError) => {
  console.log("connect failed " + JSON.stringify(err));
});

// 连接使用完毕后,主动关闭。取消相关事件的订阅。
tlsTwoWay.close((err: BusinessError) => {
  if (err) {
    console.log("close callback error = " + err);
  } else {
    console.log("close success");
  }
  tlsTwoWay.off('message');
  tlsTwoWay.off('connect');
  tlsTwoWay.off('close');
});

// 创建一个(单向认证)TLS Socket连接,返回一个TLS Socket对象。
let tlsOneWay: socket.TLSSocket = socket.constructTLSSocketInstance(); // One way authentication

// 订阅TLS Socket相关的订阅事件
tlsTwoWay.on('message', (value: SocketInfo) => {
  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);
});
tlsTwoWay.on('connect', () => {
  console.log("on connect");
});
tlsTwoWay.on('close', () => {
  console.log("on close");
});

// 绑定本地IP地址和端口。
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 5445;
tlsOneWay.bind(ipAddress, (err:BusinessError) => {
  if (err) {
    console.log('bind fail');
    return;
  }
  console.log('bind success');
});

ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 8789;
let tlsOneWaySecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions;
tlsOneWaySecureOption.ca = ["xxxx", "xxxx"];
tlsOneWaySecureOption.cipherSuite = "AES256-SHA256";

let tlsOneWayConnectOptions: socket.TLSConnectOptions = {} as socket.TLSConnectOptions;
tlsOneWayConnectOptions.address = ipAddress;
tlsOneWayConnectOptions.secureOptions = tlsOneWaySecureOption;

// 建立连接
tlsOneWay.connect(tlsOneWayConnectOptions).then(() => {
  console.log("connect successfully");
}).catch((err: BusinessError) => {
  console.log("connect failed " + JSON.stringify(err));
});

// 连接使用完毕后,主动关闭。取消相关事件的订阅。
tlsTwoWay.close((err: BusinessError) => {
  if (err) {
    console.log("close callback error = " + err);
  } else {
    console.log("close success");
  }
  tlsTwoWay.off('message');
  tlsTwoWay.off('connect');
  tlsTwoWay.off('close');
});

应用通过 TLS Socket Server 进行加密数据传输

开发步骤

服务端 TLS Socket Server 流程:

  1. import 需要的 socket 模块。

  2. 启动服务,绑定 IP 和端口号,监听客户端连接,创建并初始化 TLS 会话,加载证书密钥并验证。

  3. 订阅 TLSSocketServer 的连接事件。

  4. 收到客户端连接,通过回调得到 TLSSocketConnection 对象。

  5. 订阅 TLSSocketConnection 相关的事件。

  6. 发送数据。

  7. TLSSocketConnection 连接使用完毕后,断开连接。

  8. 取消订阅 TLSSocketConnection 以及 TLSSocketServer 的相关事件。

    import { socket } from '@kit.NetworkKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    
    let tlsServer: socket.TLSSocketServer = socket.constructTLSSocketServerInstance();
    
    let netAddress: socket.NetAddress = {
      address: '192.168.xx.xxx',
      port: 8080
    }
    
    let tlsSecureOptions: socket.TLSSecureOptions = {
      key: "xxxx",
      cert: "xxxx",
      ca: ["xxxx"],
      password: "xxxx",
      protocols: socket.Protocol.TLSv12,
      useRemoteCipherPrefer: true,
      signatureAlgorithms: "rsa_pss_rsae_sha256:ECDSA+SHA256",
      cipherSuite: "AES256-SHA256"
    }
    
    let tlsConnectOptions: socket.TLSConnectOptions = {
      address: netAddress,
      secureOptions: tlsSecureOptions,
      ALPNProtocols: ["spdy/1", "http/1.1"]
    }
    
    tlsServer.listen(tlsConnectOptions).then(() => {
      console.log("listen callback success");
    }).catch((err: BusinessError) => {
      console.log("failed" + err);
    });
    
    class SocketInfo {
      message: ArrayBuffer = new ArrayBuffer(1);
      remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
    }
    let callback = (value: SocketInfo) => {
      let messageView = '';
      for (let i: number = 0; i < value.message.byteLength; i++) {
        let uint8Array = new Uint8Array(value.message)
        let messages = uint8Array[i]
        let message = String.fromCharCode(messages);
        messageView += message;
      }
      console.log('on message message: ' + JSON.stringify(messageView));
      console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo));
    }
    tlsServer.on('connect', (client: socket.TLSSocketConnection) => {
      client.on('message', callback);
    
      // 发送数据
      client.send('Hello, client!').then(() => {
        console.log('send success');
      }).catch((err: BusinessError) => {
        console.log('send fail');
      });
    
      // 断开连接
      client.close().then(() => {
        console.log('close success');
      }).catch((err: BusinessError) => {
        console.log('close fail');
      });
    
      // 可以指定传入on中的callback取消一个订阅,也可以不指定callback清空所有订阅。
      client.off('message', callback);
      client.off('message');
    });
    
    // 取消订阅tlsServer的相关事件
    tlsServer.off('connect');

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/770873.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++之boost智能指针

1、boost智能指针 资源获取即初始化&#xff1a;在构造函数中对资源进行初始化&#xff0c;在析构函数中释放。 智能指针的本质思想是&#xff1a;将堆对象的生存期&#xff0c;用栈对象来管理。这个栈对象就是智能指针。 当new 一个堆对象的时候&#xff0c;立刻用智能指针…

共享拼购:创新商业模式引领小用户基数下的销售奇迹“

在瞬息万变的商业蓝海中&#xff0c;一个新颖且深具潜力的策略正悄然改变着游戏规则&#xff0c;它巧妙地避开了传统路径的束缚&#xff0c;以微妙却深远的调整&#xff0c;开辟出了一条通往成功的独特航道。我的一位合作伙伴&#xff0c;正是这一策略的实践者&#xff0c;他在…

Blender渲染慢?那是你还不知道这5个技巧

Blender是一款功能强大且用途广泛的软件&#xff0c;可帮助 3D 艺术家和动画师创作出色的视觉内容。如果您使用过 Blender&#xff0c;您就会知道渲染可能非常耗时。渲染时间过长可能会令人烦恼并限制创造力。 在这篇文章中&#xff0c;我们将提供一些专家提示和想法以加快 Bl…

交换机需要多大 buffer

有点违背直觉&#xff0c;但是真事儿&#xff0c;交换机过境的流越多&#xff0c;所需 buffer 越小&#xff0c;这是为什么&#xff1f; 范氏(范雅各布森&#xff0c;van jacobson)管道的 aimd 流建议 buffer_size 为 bdp&#xff0c;这很容易理解&#xff0c;因为 aimd 流最小…

OpenCV库Windows端编译方法

编译前提 &#xff08;1&#xff09;下载好所需版本的OpenCV源码&#xff0c;点击进入下载地址&#xff0c;此处以OpenCV-2.4.13.6为例&#xff0c;下载页面截图如下图所示&#xff1a; 解压后如下图所示&#xff1a; &#xff08;2&#xff09;安装好CMake软件&#xff0c;点…

规则·理解·成长:与自闭症儿童共绘记忆蓝图

在星贝育园&#xff0c;作为专注于自闭症儿童康复的专业教育者&#xff0c;我们常常遇到家长的疑惑&#xff1a;“为什么我的孩子总是记不清楚规则&#xff1f;”这个问题触及了自闭症谱系障碍&#xff08;ASD&#xff09;儿童在理解与遵守规则方面面临的独特挑战。下面&#x…

软考中级系统集成项目管理工程师备考笔记

目录 一&#xff0c;通用内容 &#xff08;一&#xff09;信息与信息化 1.1&#xff0c;信息 信息基本概念 信息的传输模型 信息的质量属性 1.2&#xff0c;信息系统 信息系统的基本概念 信息系统定义 信息系统集成 1.3&#xff0c;信息化 信息化层次 信息化的核心…

【Redis】SpringBoot连接Redis

1. 创建项目并配置文件 勾选NoSQL中的 Spring Data Redis。当然,把 Web 中的 SpringWeb 也勾选一下.方便写接口进行后续测试。 在 application.yml 中配置 2. 不同数据类型使用Demo 在SpringBoot中&#xff0c;为我们提供了StringRedisTemplate类&#xff0c;供我们处理一些文…

MYSQL8.0环境部署

创建用户 groupadd mysql useradd -g mysql mysql 删除原来的包 # rpm -qa|grep mysql # rpm -qa|grep mari mariadb-libs-5.5.68-1.el7.x86_64 # rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_64 解压 cd /usr/local & mkdir mysql cd mysql # cp mysql-8…

tauri使用github action实现跨平台编译并解决编译错误,mac已损坏,无法打开,你应该将它移到废纸篓解决办法

正常编译为跨平台结果就像上面的&#xff0c;有mac/windows/linux的安装程序&#xff0c;直接下载就可以安装使用&#xff0c;我的这个livebox桌面端仓库地址&#xff1a;GitHub - Sjj1024/LiveBox: livebox&#xff0c;里面有编译文件可以参考。今天主要讲一下遇到的问题。 官…

视频文字提取在线怎么做?5个高效提取字幕的实用方法

无论是社交媒体上的短视频&#xff0c;还是在线教育的课程视频&#xff0c;字幕都成为了不可或缺的一部分。它们不仅帮助听力障碍人士更好地理解内容&#xff0c;还能让非母语观众更容易跟上节奏。 一提到字幕&#xff0c;我们可能会想到用它来做笔记&#xff0c;但要从视频中…

UVa1321/LA2925 Dice contest

UVa1321/LA2925 Dice contest 题目链接题意分析测试数据AC 代码 题目链接 本题是2003年icpc欧洲区域赛中欧赛区的D题 题意 骰子的六面展开图如下&#xff0c;现在把骰子的六个面赋予一套权重 w i ( 1 ≤ w i ≤ 50 , 1 ≤ i ≤ 6 ) w_i(1\le w_i \le 50,1\le i\le 6) wi​(1≤…

米国政府呼吁抛弃 C 和 C++

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 很多观点认为C 或 C永远不可被…

同步互斥与通信

目录 一、同步与互斥的概念 二、同步与互斥并不简单 三、各类方法的对比 一、同步与互斥的概念 一句话理解同步与互斥&#xff1a;我等你用完厕所&#xff0c;我再用厕所。 什么叫同步&#xff1f;就是&#xff1a;哎哎哎&#xff0c;我正在用厕所&#xff0c;你等会。 什…

nginx.conf配置参数解析

nginx配置文件解析 /usr/local/nginx/conf vim /etc/security/limits.conf #配置生效只能重新启动* soft nproc 65535 #能打开的进程最大数是软限制655335,65535是最大值 * hard nproc 65535 * soft nofile 65535 # 进程打开文件数的最大值65535 * hard nof…

最新美联储会议纪要:通胀降温,但不急于降息!

KlipC报道&#xff1a;当地时间周三&#xff0c;美联储公布了6月货币政策会议纪要。纪要显示&#xff0c;数据表明有通胀放缓的迹象&#xff0c;但如果降息需要更多的证据。此外&#xff0c;多位与会者表示&#xff0c;货币政策应随时准备应对意外的经济疲软。 会议纪要显示&a…

python-字典

为什么需要字典 字典的定义 字典数据的获取 字典的嵌套 嵌套字典的内容获取 字典的注意事项&#xff1a; 字典的常用操作 新增元素 更新元素 删除元素 清空字典 汇总 字典的特点

收银系统源码-收银台营销功能-定时折扣

1. 功能描述 定时折扣&#xff1a;在特定的时间段&#xff0c;将商品以打折的方式在收银台售卖&#xff0c;例如生鲜行业&#xff0c;由于生鲜是易耗品&#xff0c;很多门店晚上都会通过打折的方式进行促销&#xff1b; 2.适用场景 新门店开业、门店周年庆、节假日等特定时间…

深度分析和对比本地大语言模型Ollama和LocalAI

前言 在充满活力的人工智能&#xff08;AI&#xff09;世界中&#xff0c;开源工具已成为开发人员和组织利用LLM&#xff08;大型语言模型&#xff09;力量的重要资源。这些工具通过提供对高级LLM模型的访问权限&#xff0c;使各种用户能够构建创新和前沿的解决方案。在众多可…

springboot @configuration注解的配置, @bean注解方法a, 在@bean注解 getb(){}需要注入a

深度解析Configuration注解 /*** General purpose AOP callback. Used when the target is dynamic or when the* proxy is not frozen.*/private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {private final AdvisedSupport advised;…