模板版本:v0.2.2
[!TIP] Gitee 地址
请到三方库的 Releases 发布地址查看配套的版本信息:@ohmi/react-native-tcp-socket Releases 。对于未发布到npm的旧版本,请参考安装指南安装tgz包。
进入到工程目录并输入以下命令:
npm install @ohmi/react-native-tcp-socket
yarn add @ohmi/react-native-tcp-socket
下面的代码展示了这个库的基本使用场景:
[!WARNING] 使用时 import 的库名不变。
import React, {useState} from 'react';
import {StyleSheet, TouchableOpacity, FlatList, Text, View} from 'react-native';
import TcpSocket from 'react-native-tcp-socket';
const ca = `-----BEGIN CERTIFICATE-----
MIIFOTCCAyGgAwIBAgIUZiAx4QlvsVTwoSPJCW7oHBut1aEwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDA4MjkxMTU5MzNaFw0yNDA5
MjgxMTU5MzNaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQC7zpsawfWsf0A4D+A2apWo87oleyYIEyi5nZo6Bo+8
Sp9dO0qFPBfVvRjDLW/E2ZRcb22I4KUNp6bXv8AvqDWRkiCsI19uuZ4CapLTLPvw
mJeJICr/ol6NIHNUMBHAW8LshojTOA9Tu5l1qw34kMVZokT/2b98FIk0z0xaPjpR
8YMYOIGHJO0J2zV3qQS60C8tvaJNvAwjhvu59J897I4putQsfnU5+xO7gsTYh4md
mzDxCMBbfxMnexwpnAXIpxvlUXpdoMZf2KV1qetEZ539qDKCvsj20ejpAHWJnbJs
uR4ZXroXer1413XzRmn9xISllq2Z3c4QX5OmCLusXwi5yrTDvs/M0PNjMsnMm1O/
OvjZznAQ8c6FnUYAGKf4K2q7HKSIn45kTrvPVeLNvb42xhQ3B5luuTraNr/oTRTK
nrteBSf3LYeK8YLCZlF9nm2ppJkV90xl7RCatU0MqmGx/VCe5b7EGgpxj8fnEm5V
GbyJ+8B5ruOLoPynejgp/2S2LdfS1oBvqdAZfjeu6sJDLS95vKUpPDoNFe4FZgFr
N3V2alzocX5D2vHacOGR2XBqZ33w53KwekPuq3hMnC9X+gCJCp/WfSBqArbcEUWF
2++Ps5cO8tJ2aq0AzD2N7epEbc6LXolXAfv1JyHszjcE5cF4CzOTMntd8BBiFxXl
YwIDAQABoyEwHzAdBgNVHQ4EFgQUtfcXe+EBtuSZNdHTxf/mFJickCswDQYJKoZI
hvcNAQELBQADggIBAI3DKyh/ylg4gzlIA5SYMlC0wFCv5rMyXAbfJHebLIs/iqEV
L+Gs9TvQnGXqcR2Rk86CgxA+4kpqOhhVOrzSO6t6YbLTZf3lxBME0p2kmbs65Llx
FFAXe5Lyg1mPWU5cgXdZ0sakf9uc16mtl6VpYnTw9aAGMdF0JSPYNbU/o734Ze+q
1GlEdsrBP3pOrmF04WVSgfdUCKqdksP8Gq1tU/pGDpT2UkzQGh+ZDz8VQePsKzAd
hgDMJbKapgEjE1cRyHAKU0JhmhRMoSXAz5svVpYm/q1dgvqi7TamoftJfXsMsOaW
eFlvUzOcS77eIE4hN2kL+fpBRwiAx8pli2RnKzd0yFnhb/LG32nwDmYhzGOMrHOO
JfpU4tWVVrIp9yY6IKRXGsj4XQ//5ofnAySTSpu4H9wOCY4o+UCv/OGx17PJT7E+
e2gyq9FGyUZg0j+GBxjlzhT32WIhpCuWqr5dTWnIlXQJSVk3RIY+zuGVOh+H6Nby
zAXyUbWUStdw8dj24PDJK89a9qCmswNTGhu7cOeOId0wxYqqkY5G6J0j57Wo1CUG
QBxQ0dpH79QAjXOAG0zE3E1ci/Sd8Nb99OSygn/Y6l0379PKkUMb6ic6G08snn00
Z3cbzglkWavGfLsNHv4r2tptJTn003Cvd8w1gYSViOA1wd3JN/e3qZPPraIM
-----END CERTIFICATE-----`;
const serverKey = `-----BEGIN PRIVATE KEY-----
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
06v4n5pCSJDPebsNaecm5HETSwAfsg==
-----END PRIVATE KEY-----`;
const keystore = require('./ca/server-keystore.p12');
interface Message {
id: number;
text: string;
user: string;
}
const getNowTime = () => {
let date = new Date();
let hours = date.getHours();
let minutes = date.getMinutes();
let seconds = date.getSeconds();
return `${hours}:${minutes}:${seconds}`;
};
let server: any = null;
let client: any = null;
let testCase = 1;
export const TcpSocketDemo = () => {
const [messages, setMessages] = useState<Message[]>([]);
const sendMessage = (msg: string, user: string) => {
let newMessage = {
id: Date.now(),
text: msg,
user: user,
};
setMessages([...messages, newMessage]);
};
const createTcpServer = () => {
server = new TcpSocket.Server();
server.listen({port: 0, host: '127.0.0.1', reuseAddress: true}, () => {
const port = server.address()?.port;
if (!port) throw new Error('Server port not found');
console.log('TcpSocketDemo:tcpServer start listen success on:'+port);
});
server.on('connection', (socket: any) => {
console.log('TcpSocketDemo:tcpServer on connection!');
socket.on('data', (data: any) => {
switch (testCase) {
case 1:
console.log(
'TcpSocketDemo:tcpServer received data:' + JSON.stringify(data),
);
sendMessage(`received data: ${data}`, 'tcpServer');
let time = getNowTime();
socket.write(`${time} Hello, tcpClient!`);
break;
case 2:
console.log(
`TcpSocketDemo:tcpServer Received ${data.length} bytes of data.`,
);
socket.pause();
console.log(
'TcpSocketDemo:tcpServer There will be no additional data for 1 second.',
);
setTimeout(() => {
console.log(
'TcpSocketDemo:tcpServer Now data will start flowing again.',
);
socket.resume();
}, 1000);
break;
case 3:
let dataLen = data.length;
let time1 = getNowTime();
console.log(
'TcpSocketDemo:tcpServer client received data: ' +
dataLen +
' bytes',
);
sendMessage(
`${time1} received data: ${dataLen} bytes`,
'tcpServer',
);
break;
default:
console.log(
'TcpSocketDemo:tcpServer socket received data:' +
JSON.stringify(data),
);
}
});
socket.on('error', (error: any) => {
let errorMsg = '';
if (error) {
errorMsg = JSON.stringify(error);
}
console.log('TcpSocketDemo:tcpServer socket on error ' + errorMsg);
});
socket.on('close', (error: any) => {
let errorMsg = '';
if (error) {
errorMsg = JSON.stringify(error);
}
console.log('TcpSocketDemo:tcpServer socket on close ' + errorMsg);
});
});
server.on('error', (error: any) => {
console.log('TcpSocketDemo:tcpServer on error ' + JSON.stringify(error));
});
server.on('close', () => {
console.log('TcpSocketDemo:tcpServer closed');
});
};
const createTcpClient = () => {
client = new TcpSocket.Socket();
const port = server.address()?.port;
if (!port) throw new Error('Server port not found');
let options = {
port: port,
host: '127.0.0.1',
localAddress: '127.0.0.1',
reuseAddress: true,
localPort: 20000,
interface: 'wifi',
};
client.connect(options, () => {
console.log('TcpSocketDemo:tcpClient connect success');
});
client.on('data', (data: any) => {
console.log(
'TcpSocketDemo:tcpClient received data: ' +
(data.length < 500 ? data : data.length + ' bytes'),
);
sendMessage(`received data: ${data}`, 'tcpClient');
});
client.on('connect', () => {
console.log(
'TcpSocketDemo:tcpClient on connect:' +
JSON.stringify(client.address()),
);
});
client.on('drain', () => {
console.log('TcpSocketDemo:tcpClient drained');
});
client.on('error', (error: any) => {
if (error) {
console.log('TcpSocketDemo:tcpClient error ' + JSON.stringify(error));
}
});
client.on('close', (error: any) => {
let errorMsg = '';
if (error) {
errorMsg = JSON.stringify(error);
}
console.log('TcpSocketDemo:tcpClient closed ' + errorMsg);
});
};
const tcpSendData = () => {
testCase = 1;
let time = getNowTime();
client.write(`${time} Hello, tcpServer!`);
};
const tcpClose = () => {
client.destroy();
server.close();
client = null;
server = null;
};
const tcpPauseResume = () => {
testCase = 2;
let i = 0;
const MAX_ITER = 3000;
write();
async function write() {
let ok = true;
while (i <= MAX_ITER && ok) {
i++;
const buff = ' ->' + i + '<- ';
ok = client.write(buff);
}
if (!ok) {
client.once('drain', write);
}
}
};
const tcpLongData = () => {
testCase = 3;
const hugeData = 'x'.repeat(5 * 1024);
client.end(hugeData, 'utf8');
console.log('TcpSocketDemo:tcpClient end hugeData...');
};
const createTlsServer = () => {
server = new TcpSocket.TLSServer();
server.setSecureContext({
key: serverKey,
cert: ca,
keystore: keystore,
});
server.on('secureConnection', (socket: any) => {
console.log(
'TcpSocketDemo:TlsServer on secureConnection:' +
JSON.stringify(socket.address()),
);
socket.on('data', (data: any) => {
switch (testCase) {
case 1:
console.log(
'TcpSocketDemo:tlsServer received data:' + JSON.stringify(data),
);
sendMessage(`received data: ${data}`, 'tlsServer');
let time = getNowTime();
socket.write(`${time} Hello, tlsClient!`);
break;
case 2:
console.log(
`TcpSocketDemo:tlsServer Received ${data.length} bytes of data.`,
);
socket.pause();
console.log(
'TcpSocketDemo:tlsServer There will be no additional data for 1 second.',
);
setTimeout(() => {
console.log(
'TcpSocketDemo:tlsServer Now data will start flowing again.',
);
socket.resume();
}, 1000);
break;
case 3:
let dataLen = data.length;
let time1 = getNowTime();
console.log(
'TcpSocketDemo:tlsServer client received data: ' +
dataLen +
' bytes',
);
sendMessage(
`${time1} received data: ${dataLen} bytes`,
'tlsServer',
);
break;
default:
console.log(
'TcpSocketDemo:tlsServer socket received data:' +
JSON.stringify(data),
);
}
});
socket.on('error', (error: any) => {
console.log(
'TcpSocketDemo:TlsServer secureConnection socket error ' +
JSON.stringify(error),
);
});
socket.on('close', (error: any) => {
console.log(
'TcpSocketDemo:TlsServer secureConnection socket closed ' +
(error ? JSON.stringify(error) : ''),
);
});
});
server.on('error', (error: any) => {
console.log('TcpSocketDemo:TlsServer on error ' + JSON.stringify(error));
});
server.on('close', () => {
console.log('TcpSocketDemo:TlsServer closed');
});
server.listen({port: 9999, host: '127.0.0.1', reuseAddress: true}, () => {
console.log('TcpSocketDemo:tlsServer start listen success!');
});
};
const createTlsClient = () => {
let clientSocket = new TcpSocket.Socket();
client = new TcpSocket.TLSSocket(clientSocket, {ca});
clientSocket.on('error', error => {
console.log(
'TcpSocketDemo:TlsClient clientSocket error',
error ? JSON.stringify(error) : '',
);
});
clientSocket.on('close', hadError => {
console.log(
'TcpSocketDemo:TlsClient clientSocket close ' +
(hadError ? JSON.stringify(hadError) : ''),
);
});
clientSocket.connect(
{
port: 9999,
host: '127.0.0.1',
reuseAddress: true,
localPort: 20000,
interface: 'wifi',
},
() => {
console.log('TcpSocketDemo:TlsClient clientSocket connect success.');
},
);
client.on('secureConnect', () => {
console.log(
'TcpSocketDemo:TlsClient on secureConnect:' +
JSON.stringify(client.address()),
);
});
client.on('connect', () => {
console.log(
'TcpSocketDemo:TlsClient on connect:' +
JSON.stringify(client.address()),
);
});
client.on('drain', () => {
console.log('TcpSocketDemo:TlsClient Client drained');
});
client.on('data', (data: any) => {
console.log(
'TcpSocketDemo:TlsClient received data: ' +
(data.length < 500 ? data : data.length + ' bytes'),
);
sendMessage(
`received data: ${data.length < 500 ? data : data.length + ' bytes'}`,
'tlsClient',
);
});
client.on('error', (error: any) => {
console.log('TcpSocketDemo:TlsClient error ' + JSON.stringify(error));
});
client.on('close', (error: any) => {
console.log(
'cpSocketDemo:TlsClient closed ' + (error ? JSON.stringify(error) : ''),
);
});
};
return (
<View style={styles.container}>
<FlatList
data={messages}
renderItem={({item}) => (
<View style={styles.message}>
<Text style={styles.messageText}>
{item?.user}: {item?.text}
</Text>
</View>
)}
keyExtractor={item => item.id.toString()}
/>
<TouchableOpacity onPress={createTcpServer} style={styles.moduleButton}>
<Text style={styles.buttonText}>创建TCP服务器</Text>
</TouchableOpacity>
<TouchableOpacity onPress={createTcpClient} style={styles.moduleButton}>
<Text style={styles.buttonText}>创建TCP客户端</Text>
</TouchableOpacity>
<TouchableOpacity onPress={tcpSendData} style={styles.moduleButton}>
<Text style={styles.buttonText}>客户端和服务器通信</Text>
</TouchableOpacity>
<TouchableOpacity onPress={tcpPauseResume} style={styles.moduleButton}>
<Text style={styles.buttonText}>数据的暂停与恢复</Text>
</TouchableOpacity>
<TouchableOpacity onPress={tcpLongData} style={styles.moduleButton}>
<Text style={styles.buttonText}>长数据传输</Text>
</TouchableOpacity>
<TouchableOpacity onPress={tcpClose} style={styles.moduleButton}>
<Text style={styles.buttonText}>关闭连接</Text>
</TouchableOpacity>
<TouchableOpacity onPress={createTlsServer} style={styles.moduleButton}>
<Text style={styles.buttonText}>创建TLS服务器</Text>
</TouchableOpacity>
<TouchableOpacity onPress={createTlsClient} style={styles.moduleButton}>
<Text style={styles.buttonText}>创建TLS客户端</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#fff',
},
message: {
marginVertical: 10,
padding: 10,
backgroundColor: '#aaa',
},
messageText: {
fontSize: 16,
},
moduleButton: {
marginBottom: 5,
backgroundColor: 'deepskyblue',
height: 34,
borderRadius: 10,
},
buttonText: {
fontSize: 18,
fontWeight: '400',
color: '#fff',
textAlign: 'center',
lineHeight: 32,
verticalAlign: 'middle',
},
});
本库已经适配了 Codegen
,在使用前需要主动执行生成三方库桥接代码,详细请参考 Codegen 使用文档。
目前 HarmonyOS 暂不支持 AutoLink,所以 Link 步骤需要手动配置。
首先需要使用 DevEco Studio 打开项目里的 HarmonyOS 工程 harmony
{
...
"overrides": {
"@rnoh/react-native-openharmony" : "./react_native_openharmony"
}
}
目前有两种方法:
- 通过 har 包引入(在 IDE 完善相关功能后该方法会被遗弃,目前首选此方法);
- 直接链接源码。
方法一:通过 har 包引入(推荐)
[!TIP] har 包位于三方库安装路径的
harmony
文件夹下。
打开 entry/oh-package.json5
,添加以下依赖
"dependencies": {
"@rnoh/react-native-openharmony" : "file:../react_native_openharmony",
"@ohmi/react-native-tcp-socket": "file:../../node_modules/@ohmi/react-native-tcp-socket/harmony/tcp_socket.har"
}
点击右上角的 sync
按钮
或者在终端执行:
cd entry
ohpm install
方法二:直接链接源码
[!TIP] 如需使用直接链接源码,请参考直接链接源码说明
打开 entry/src/main/ets/RNPackagesFactory.ts
,添加:
...
+ import {TcpSocketPackage} from '@ohmi/react-native-tcp-socket/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [new SamplePackage(ctx),
+ new TcpSocketPackage(ctx)
];
}
打开 entry/src/main/cpp/CMakeLists.txt
,添加:
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(NODE_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../node_modules")
+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../react-native-harmony/harmony/cpp")
set(LOG_VERBOSITY_LEVEL 1)
set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use
add_compile_definitions(WITH_HITRACE_SYSTRACE)
add_subdirectory("${RNOH_CPP_DIR}" ./rn)
# RNOH_BEGIN: manual_package_linking_1
add_subdirectory("../../../../sample_package/src/main/cpp" ./sample-package)
+ add_subdirectory("${OH_MODULES}/@ohmi/react-native-tcp-socket/src/main/cpp" ./tcp_socket)
# RNOH_END: manual_package_linking_1
file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")
add_library(rnoh_app SHARED
${GENERATED_CPP_FILES}
"./PackageProvider.cpp"
"${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
target_link_libraries(rnoh_app PUBLIC rnoh)
# RNOH_BEGIN: manual_package_linking_2
target_link_libraries(rnoh_app PUBLIC rnoh_sample_package)
+ target_link_libraries(rnoh_app PUBLIC rnoh_tcp_socket)
# RNOH_END: manual_package_linking_2
打开 entry/src/main/cpp/PackageProvider.cpp
,添加:
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
#include "SamplePackage.h"
+ #include "RNTcpSocketPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<RNOHGeneratedPackage>(ctx),
std::make_shared<SamplePackage>(ctx),
+ std::make_shared<RNTcpSocketPackage>(ctx),
};
}
点击右上角的 sync
按钮
或者在终端执行:
cd entry
ohpm install
然后编译、运行即可。
要使用此库,需要使用正确的 React-Native 和 RNOH 版本。另外,还需要使用配套的 DevEco Studio 和 手机 ROM。
请到三方库相应的 Releases 发布地址查看 Release 配套的版本信息:@ohmi/react-native-tcp-socket Releases
需要获取网络信息权限:"ohos.permission.GET_NETWORK_INFO"和使用网络权限:"ohos.permission.INTERNET",配置方法如下:
打开entry/src/main/module.json5
,添加:
"requestPermissions": [
...
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
}
]
[!TIP] "Platform"列表示该属性在原三方库上支持的平台。
[!TIP] "HarmonyOS Support"列为 yes 表示 HarmonyOS 平台支持该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
Name | Description | Type | Required | Platform | HarmonyOS Support |
---|---|---|---|---|---|
connect(options, callback) | Same as createConnection,Creating a TCP Socket | function | no | Android,iOS | yes |
createServer(connectionListener) | Creating a TCP Server | function | no | Android,iOS | yes |
createConnection(options, callback) | Creating a TCP Socket | function | no | Android,iOS | yes |
createTLSServer(options, connectionListener) | Creating a TLS-based TCP Server | function | no | Android,iOS | no |
connectTLS | Creating a TLS-based encrypted connection | function | no | Android,iOS | yes |
isIP | Check whether a character string is an IP address | function | no | Android,iOS | yes |
isIPv4 | Check whether a character string is an IPv4 address | function | no | Android,iOS | yes |
isIPv6 | Check whether a character string is an IPv6 address | function | no | Android,iOS | yes |
Server | TCP Server Object | object | no | Android,iOS | yes |
Socket | TCP Socket Object | object | no | Android,iOS | yes |
TLSServer | TLS Server Object | object | no | Android,iOS | yes |
TLSSocket | TLS Socket Object | object | no | Android,iOS | yes |
Name | Description | Type | Required | Platform | HarmonyOS Support |
---|---|---|---|---|---|
address() | Returns the bound address , the address family name, and port of the server as reported by the operating system if listening |
function | no | Android,iOS | yes |
listen(options, callback) | Start a server listening for connections | function | no | Android,iOS | yes |
close(callback) | Stops the server from accepting new connections and keeps existing connections | function | no | Android,iOS | yes |
getConnections(callback) | Asynchronously get the number of concurrent connections on the server | function | no | Android,iOS | yes |
listening | whether to enable the listening | boolean | no | Android,iOS | yes |
on('close') | Triggered when the server is shut down | event | no | Android,iOS | yes |
on('connection') | Triggered when the server receives a new connection | event | no | Android,iOS | yes |
on('error') | Triggered when an error occurs on the server | event | no | Android,iOS | yes |
on('listening') | Triggered when the server starts listening | event | no | Android,iOS | yes |
Name | Description | Type | Required | Platform | HarmonyOS Support |
---|---|---|---|---|---|
address() | Returns the bound address , the address family name and port of the socket as reported |
function | no | Android,iOS | yes |
destroy() | Ensures that no more I/O activity happens on this socket. Destroys the stream and closes the connection | function | no | Android,iOS | yes |
end() | Half-closes the socket. i.e., it sends a FIN packet. It is possible the server will still send some data | function | no | Android,iOS | yes |
setEncoding(encoding) | Set the encoding for the socket as a Readable Stream. By default, no encoding is assigned and stream data will be returned as Buffer objects |
function | no | Android,iOS | yes |
setNoDelay(noDelay) | Set no delay | function | no | Android,iOS | no |
setTimeout() | Sets the socket to timeout after timeout milliseconds of inactivity on the socket. By default TcpSocket do not have a timeout |
function | no | Android,iOS | yes |
write(buffer, encoding, cb) | Sends data on the socket. The second parameter specifies the encoding in the case of a string — it defaults to UTF8 encoding | function | no | Android,iOS | yes |
pause() | Pauses the reading of data. That is, 'data' events will not be emitted. Useful to throttle back an upload |
function | no | Android,iOS | yes |
resume() | Resumes reading after a call to socket.pause()
|
function | no | Android,iOS | yes |
writableNeedDrain | whether need to wait for data to be written to the socket | boolean | no | Android,iOS | yes |
bytesRead | Indicates the number of bytes of data that have been read from the socket | number | no | Android,iOS | yes |
bytesWritten | get the number of bytes last written to the socket | number | no | Android,iOS | yes |
connecting | whether the current socket is being connected | boolean | no | Android,iOS | yes |
destroyed | Whether the socket has been destroyed | boolean | no | Android,iOS | yes |
localAddress | Local ip address | string | no | Android,iOS | yes |
localPort | Local port | number | no | Android,iOS | yes |
remoteAddress | remote server IP address | string | no | Android,iOS | yes |
remoteFamily | remote server IP address type | string | no | Android,iOS | yes |
remotePort | remote server port | number | no | Android,iOS | yes |
pending | Whether has pending data to be sent to the remote server | boolean | no | Android,iOS | yes |
timeout | The timeout period for the socket, in milliseconds. The default timeout period is 30 seconds | number | no | Android,iOS | yes |
readyState | the state of socket,0 : not connected,1 :connected,2: closing,3:closed |
number | no | Android,iOS | yes |
on('pause') | Triggered when pauses the reading of data | event | no | Android,iOS | yes |
on('resume') | Triggered when Resumes the reading of data | event | no | Android,iOS | yes |
on('close') | Triggered when socket is closed | event | no | Android,iOS | yes |
on('connect') | Triggered when socket is connected | event | no | Android,iOS | yes |
on('data') | Triggered when socket receives data | event | no | Android,iOS | yes |
on('drain') | Triggered when the buffer becomes empty, indicating that data can be written to the socke | event | no | Android,iOS | yes |
on('error') | Triggered when an error occurs on the socket | event | no | Android,iOS | yes |
on('timeout') | Triggered When the connection or data transmission times out | event | no | Android,iOS | yes |
[!TIP] TLSServer继承自Server对象,拥有Server对象的所有属性、方法和事件,以下仅列出其独有的属性。
Name | Description | Type | Required | Platform | HarmonyOS Support |
---|---|---|---|---|---|
setSecureContext(options) | Set Security Context | function | no | Android,iOS | no |
on('secureConnection') | Triggered When a secure TLS connection is established | event | no | Android,iOS | no |
[!TIP] TLSSocket继承自Socket对象,拥有Socket对象的所有属性、方法和事件,以下仅列出其独有的属性。
Name | Description | Type | Required | Platform | HarmonyOS Support |
---|---|---|---|---|---|
getCertificate() | Get a Local Certificate Information | function | no | Android | yes |
getPeerCertificate() | Get the Certificate Information of the Remote Server | function | no | Android | yes |
on('secureConnect') | Triggered When a secure connection is established | event | no | Android,iOS | no |
- [ ] 目前无法实现多线程: issue#3
- [ ] 获取证书只有异步接口,目前返回值是一个promise,与安卓上同步接口不一致: issue#4
- [ ] setNODelay设置ture和false效果没有区别 issue#5
- [ ] 在createTLSServer并连接后,没有on('secureConnection')和on('secureConnect')的回调 issue#6
本项目基于 The MIT License (MIT) ,请自由地享受和参与开源。