本文介绍: 需要使用net 模块,是 node.js核心模块,直接可以引入使用const net = require(‘net‘);Node.js服务端客户端区分开了,使用起来还是非常的简单服务端大概就是监…

Hi I’m Shendi


Node.js之TCP(net)


最近使用Nodejs编写程序需要用到自己编写分布式工具,于是需要将Java版的用NodeJs重新写一遍,需要使用到TCP通信,于是在这里记录下Node.js TCP 的使用方法

依赖

需要使用net 模块,是 node.js 的核心模块,直接可以引入使用

const net = require('net');

TCP服务端

Node.js服务端客户端区分开了,使用起来还是非常的简单服务端大概就是监听连接读写数据

创建TCP服务端

通过 createServer 函数创建一个服务端,函数接收一个回调函数用于处理新的客户端连接回调函数一个参数 socket代表客户端连接,通过socket读取客户端发送数据,以及发送数据客户端

函数返回 net.Server

示例如下

var server = net.createServer(function (socket) {
    console.log("有新的客户连接了");
});

监听端口

创建服务端后,还需要指定监听的端口,相当于启动服务

通过 listen 函数

var port = 80;
server.listen(port, function () {
    // 在启动成功后执行
    console.log(`服务端已启动端口${that.port}`);
});

获取客户ip

创建TCP服务部分传递一个回调函数回调函数有一参数 socket,通过这个参数处理关于客户端的操作,包括获取ip

通过 remoteAddress 获取ip,但是获取到的ipipv6格式的,其中包含ipv4地址

IP地址以::ffff:开头表示该IP地址一个IPv4地址嵌入在IPv6地址中的表示方式。IPv6地址是128位长,而IPv4地址只有32位长,为了在IPv6环境使用IPv4地址,可以使用该表示方式。

在这里插入图片描述

于是要拿到具体ip需要进行额外操作这里我就使用最简单的,字符串截取

let ip = socket.remoteAddress;
ip = ip.substring(ip.lastIndexOf(":") + 1);

这样就拿到正确的ip了

设置超时时间

使用 socket.setTimeout设置超时时间函数接收两个参数一个超时时间(秒),一个回调函数。

当socket在指定时间没有收到任何新的数据时,将会触发回调

例如五秒没有收到数据关闭连接

socket.setTimeout(5000, () => {
    socket.end();
});

读取数据

通过 on 监听 data 事件读取数据

// data 为 Buffer 类型
socket.on("data", function (data) {
    console.log(data.toString());
});

因为是 TCP,有可能粘包、拆包之类的,所以一般都有对应自定义协议,以及缓冲区

例如一个完整协议数据以字节 20 结尾,示例代码如下

// 读取的数据缓存
var readData = Buffer.from([]);

// 收到数据触发data事件
socket.on("data", function (data) {
    readData = Buffer.concat([readData, data]);
    let index = readData.indexOf(Buffer.from([20]));
    if (index != -1) {
        // 读取到了一个完整的协议数据,进行处理
        let pData = readData.subarray(0, index + 1);
        // 处理...
        console.log(pData.toString());
        // 处理完从缓存移除部分数据
        readData = readData.subarray(index + 1, readData.length);
    } else {
        // 没有读取完整的协议数据,不做操作
    }
});

发送数据

通过 write发送数据,其中第一个参数为要发送的数据,可以字符串和Uint8Array(Buffer是其子类

第二个参数发送成功的回调

socket.write("hello,world", function () {
    console.log(`发送成功,数据长度为:${socket.bytesWritten}`);
});

事件处理

不管是服务端还是socket,都可以通过 on 来监听事件,同读取数据那样

服务端Server的事件

名称 描述
listening 调用 server.listen触发
connection 当新连接创建后会被触发。socket 是 net.Socket实例
close 服务器关闭时会触发。注意,如果存在连接,这个事件不会被触发直到所有的连接关闭
error 发生错误时触发

Socket的事件

名称 描述
lookup 解析域名后,但在连接前,触发这个事件。对 UNIX sokcet 不适用
connect 成功建立 socket 连接时触发
data 当接收到数据时触发
end socket 另一端发送 FIN 包时,触发该事件
timeout socket 空闲超时时触发,仅是表明 socket 已经空闲用户必须手动关闭连接
drain 当写缓存为空时触发。可用来控制上传
error 错误发生时触发
close 当 socket 完全关闭时触发。参数 had_error 是布尔值,它表示是否因为传输错误导致 socket 关闭

报错处理 Error: read ECONNRESET,导致服务程序挂掉

错误如下

在这里插入图片描述

这个问题出现是客户没有调用 close 关闭连接,但客户端挂了(例如任务管理器强行停止),但这种情况是很常见的,对于服务端来说,不可能因为这种小问题而导致整个服务端程序挂掉

解决办法就是给socket增加error事件

socket.on('error', function(err) {
    console.log(`客户端出错,err${err}`);
    that.connNum--;
});

这样出错会被捕获,不会导致整个程序挂掉了

TCP客户端

客户端的使用方式大体和服务端差不多

创建 TCP 客户端

通过 net 模块createConnection 创建客户端,函数返回 net.Socket,与上面服务端的Socket是一样的类型,所以使用方法也是一样的

函数有两个参数第一个端口号第二个主机名,域名/地址

let socket = net.createConnection(port, host);

具体使用

与服务端部分的socket使用是一样的,所以这里就直接贴出示例代码

let socket = net.createConnection(80, "127.0.0.1");

// 发送数据
socket.write(Buffer.from("Shendi"));
socket.on('data', (data) => {
    console.log(`收到数据: ${data}`);
});

conn.client.on('end', function(data) {
   	console.log(`客户端连连接关闭`);
});

conn.client.on('error', function(err) {
    console.log(`客户端连接出错,err:${err}`);
});

END

原文地址:https://blog.csdn.net/qq_41806966/article/details/134497901

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_24326.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注