一文搞懂如何使用node.js进行tcp网络通信(代码片段)

华为云 华为云     2023-01-05     717

关键词:

摘要: 网络是通信互联的基础,Node.js提供了net、http、dgram等模块,分别用来实现TCP、HTTP、UDP的通信,本文主要对使用Node.js的TCP通信部份进行实践记录。

本文分享自华为云社区《一文搞懂如何使用Node.js进行TCP网络通信》,作者:lwq1228 。

1、构建TCP服务器

1.1、使用Node.js创建TCP服务器

为了使用Node.js创建TCP服务器,首先要调用require(‘net’)来加载net模块,然后调用net模块的createServer方法就可以轻松地创建一个TCP服务器,语法格式如下:

net.createServer([options][, connectionListener])

options是一个对象参数值,有两个布尔类型的属性allowHalfOpen和pauseOnConnect。这两个属性默认都是false;
connectionListener是一个当客户端与服务端建立连接时的回调函数,这个回调函数以socket端口对象作为参数。

1.2、监听客户端的连接

使用TCP服务器的listen方法就可以开始监听客户端的连接,语法格式如下:

server.listen(port[, host][, backlog][, callback]);

port:为需要监听的端口号,参数值为0的时候将随机分配一个端口号;
host:服务器地址;
backlog:连接等待队列的最大长度;
callback:回调函数。

以下代码可以创建一个TCP服务器并监听8001端口:

//引入net模块
const net = require('net');
//创建TCP服务器
const server = net.createServer(function (socket) 
    console.log('有新的客户端接入');
);
//设置监听端口
server.listen(8001, function () 
    console.log('服务正在监听中。。。')
);

运行这段代码,可以在控制台看到执行了listen方法的回调函数,如图所示:

可以使用相应的TCP客户端或者调试工具来连接这个已经创建好的TCP服务器。例如,要使用Windows的Telnet就可以用以下命令来连接:

telnet localhost 8001

连接成功后可以看到控制台打印了“有新的客户端接入”字样,表明createServer方法的回调函数已经执行,说明已经成功连接到这个创建好的TCP服务器。

server.listen()方法其实触发的是server下的listening事件,所以也可以手动监听listening事件,代码如下:

//设置监听端口
server.listen(8001);
//设置监听时的回调函数
server.on('listening', function () 
    console.log("服务正在监听中。。。")
);

除了listening事件外,TCP服务器还支持以下事件:

connection:当有新的链接创建时触发,回调函数的参数为socket连接对象。
close:TCP服务器关闭的时候触发,回调函数没有参数。
error:TCP服务器发生错误的时候触发,回调函数的参数为error对象。

下列代码通过net.Server类来创建一个TCP服务器,添加以上事件:

//引入net模块
const net = require('net');
//实例化一个服务器对象
const server = new net.Server();
//监听connection事件
server.on('connection', function (socket) 
    console.log('有新的客户端接入');
);
//设置监听端口
server.listen(8001);
//设置监听时的回调函数
server.on('listening', function () 
    console.log('服务正在监听中。。。');
);
//设置关闭时的回调函数
server.on('close', function () 
    console.log('服务已关闭');
);
//设置出错时的回调函数
server.on('error', function (err) 
    console.log('服务运行异常', err);
);

1.3、查看服务器监听的地址

当创建了一个TCP服务器后,可以通过server.address()方法来查看这个TCP服务器监听的地址,并返回一个JSON对象,因为这个方法返回的是TCP服务器监听的地址信息,所以应该在调用了server.listen()方法或者绑定了事件listening中的回调函数中调用该方法。这个对象的属性有:

port:TCP服务器监听的端口号;
family:说明TCP服务器监听的地址是IPv6还是IPv4;
address:TCP服务器监听的地址。

代码如下:

//引入net模块
const net = require('net');
//创建TCP服务器
const server = net.createServer(function (socket) 
    console.log('有新的客户端接入');
);
//设置监听端口
server.listen(8001);
//设置监听时的回调函数
server.on('listening', function () 
    //获取地址信息
    let address = server.address();
    //获取地址详细信息
    console.log("服务器监听的端口是:" + address.port);
    console.log("服务器监听的地址是:" + address.address);
    console.log("服务器监听的地址类型是:" + address.family);
);

运行结果如图:

1.4、连接服务器的客户端数量

创建一个TCP服务器后,可以通过server.getConnections()方法获取连接这个TCP服务器的客户端数量。这个方法是一个异步的方法,回调函数有两个参数:

第一个参数为error对象。
第二个参数为连接TCP服务器的客户端数量。

除了获取连接数外,也可以通过设置TCP服务器的maxConnections属性来设置这个TCP服务器的最大连接数。当连接数超过最大连接数的时候,服务器将拒绝新的连接。如下代码设置这个TCP服务器的最大连接数为3。

//引入net模块
const net = require('net');
//创建TCP服务器
const server = net.createServer(function (socket) 
    console.log('有新的客户端接入');
    //设置最大连接数量
    server.maxConnections = 3;
    server.getConnections(function (err, count) 
        console.log("当前连接的客户端个数为:" + count);
    );
);
//设置监听端口
server.listen(8001, function () 
    console.log("服务正在监听中。。。")
);

运行这段代码,并尝试用多个客户端连接。可以发现当客户端连接数超过3的时候,新的客户端就无法连接这个服务器了,如图所示:

1.5、获取客户端发送的数据

createServer方法的回调函数参数是一个net.Socket对象(服务器所监听的端口对象),这个对象同样也有一个address()方法,用来获取TCP服务器绑定的地址,同样也是返回一个含有port、family、address属性的对象。通过socket对象可以获取客户端发送的流数据,每次接收到数据的时候触发data事件,通过监听这个事件就可以在回调函数中获取客户端发送的数据,代码如下:

//引入net模块
const net = require('net');
//创建TCP服务器
const server = net.createServer(function (socket) 
    //监听data事件
    socket.on("data", function (data) 
        //打印数据
        console.log("接收到数据:" + data.toString());
    );
);
//设置监听端口
server.listen(8001, function () 
    console.log("服务正在监听中。。。")
);

测试结果如下:

socket对象除了有data事件外,还有connect、end、error、timeout等事件。

1.6、发送数据给客户端

调用socket.write()可以使TCP服务器发送数据,这个方法只有一个必需参数,就是需要发送的数据;第二个参数为编码格式,可选。同时,可以为这个方法设置一个回调函数。当有用户连接TCP服务器的时候,将发送数据给客户端,代码如下:

//引入net模块
const net = require('net');
//创建TCP服务器
const server = net.createServer(function (socket) 
    //设置消息内容
    const message = "Hello Client......";
    //发送数据
    socket.write(message, function () 
        const writeSize = socket.bytesWritten;
        console.log("数据发送成功,数据长度为:" + writeSize);
    );

    //监听data事件
    socket.on("data", function (data) 
        const readSize = socket.bytesRead;
        //打印数据
        console.log("接收到数据为:" + data.toString(), ";接收的数据长度为:" + readSize);
    );
);
//设置监听端口
server.listen(8001, function () 
    console.log("服务正在监听中。。。")
);

测试结果如下:

在上面这段代码中还用到了socket对象的bytesWritten和bytesRead属性,这两个属性分别代表着发送数据的字节数和接收数据的字节数。除了上面这两个属性外,socket对象还有以下属性:

socket.localPort:本地端口的地址;
socket.localAddress:本地IP地址;
socket.remotePort:进程端口地址;
socket.remoteFamily:进程IP协议族;
socket.remoteAddress:进程IP地址。

2、构建TCP客户端

Node.js在创建一个TCP客户端的时候同样使用的是net(网络)模块。

2.1、使用Node.js创建TCP客户端

为了使用Node.js创建TCP客户端,首先要调用require(‘net’)来加载net模块。创建一个TCP客户端只需要创建一个连接TCP客户端的socket对象即可:

//引入net模块
const net = require('net');
//创建TCP客户端
const client = new net.Socket();

创建一个socket对象的时候可以传入一个json对象。这个对象有以下属性:

fd:指定一个存在的文件描述符,默认值为null;
readable:是否允许在这个socket上读,默认值为false;
writeable:是否允许在这个socket上写,默认值为false;
allowHalfOpen:该属性为false时,TCP服务器接收到客户端发送的一个FIN包后,将会回发一个FIN包;该属性为true时,TCP服务器接收到客户端发送的一个FIN包后不会回发FIN包。

2.2、连接TCP服务器

创建了一个socket对象后,调用socket对象的connect()方法就可以连接一个TCP服务器,代码如下:

//引入net模块
const net = require('net');
//创建TCP客户端
const client = new net.Socket();
//设置连接的服务器
client.connect(8001, '127.0.0.1', function () 
    console.log("连接服务器成功");
);

连接成功如下图所示:

2.3、获取从TCP服务器发送的数据

socket对象有data、error、close、end等事件,因可以通过监听data事件来获取从TCP服务器发送的数据,代码如下:

//引入net模块
const net = require('net');
//创建TCP客户端
const client = new net.Socket();
//设置连接的服务器
client.connect(8001, '127.0.0.1', function () 
    console.log("连接服务器成功");
);
//监听data事件
client.on("data", function (data) 
    //打印数据
    console.log("接收到数据为:" + data.toString());
);

先启动TCP服务端,再运行上面客户端,可以发现命令行中已经输出了来自服务端的数据,说明此时已经实现了服务端和客户端之间的通信:

2.4、向TCP服务器发送数据

因为TCP客户端是一个socket对象,所以可以使用以下代码来向TCP服务器发送数据:

//引入net模块
const net = require('net');
//创建TCP客户端
const client = new net.Socket();
//设置连接的服务器
client.connect(8001, '127.0.0.1', function () 
    console.log("连接服务器成功");
    //给服务端发送数据
    client.write("Hello Server......");
);
//监听data事件
client.on("data", function (data) 
    //打印数据
    console.log("接收到数据为:" + data.toString());
);
//监听end事件
client.on("end", function () 
    console.log("客户端发送数据结束")
);

客户端控制台输出:

服务端控制台输出:

至此使用Node.js进行TCP网络通信完成,如有不对的地方欢迎指正

点击关注,第一时间了解华为云新鲜技术~

一文搞懂tcp/ip三次握手四次挥手(用wireshark软件对通信过程进行抓包)让连接过程变得具象化

一文搞懂TCP/IP三次握手四次挥手Wireshark安装基本使用三次握手查看本机IP(客户端IP地址)查看服务器IP地址建立连接查看三次握手过程四次挥手四次挥手基础打开抓包过程查看四次挥手过程对于学习互联网的人,三次握手四次... 查看详情

一文搞懂tcp/ip三次握手四次挥手(用wireshark软件对通信过程进行抓包)让连接过程变得具象化

一文搞懂TCP/IP三次握手四次挥手Wireshark安装基本使用三次握手查看本机IP(客户端IP地址)查看服务器IP地址建立连接查看三次握手过程四次挥手四次挥手基础打开抓包过程查看四次挥手过程对于学习互联网的人,三次握手四次... 查看详情

一文搞懂rpc原理(代码片段)

...处理能力和吞吐量带来了近似于无限制提升的可能。在OSI网络通信模 查看详情

一文搞懂tcp的三次握手和四次挥手

参考技术ATCP的三次握手和四次挥手实质就是TCP通信的连接和断开。三次握手:为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系,并建... 查看详情

一文带你认识nodejs

​node.js初探Node.js是一个JS的服务端运行环境,简单的来说,它是在JS语言规范的基础上,封装了一些服务端的运行时对象,让我们能够简单实现非常多的业务功能。如果我们只使用JS的话,实际上只是能进行一些简单的逻辑运算... 查看详情

一文搞懂cpu如何控制i/o设备

1接口和设备:经典适配器模式输入输出设备不只是一个设备。大部分输入输出设备,都有:它的接口(Interface)实际的I/O设备(ActualI/ODevice)硬件设备并非直接接入到总线上和CPU通信,而是通过接... 查看详情

一文搞懂cpu如何控制i/o设备

1接口和设备:经典适配器模式输入输出设备不只是一个设备。大部分输入输出设备,都有:它的接口(Interface)实际的I/O设备(ActualI/ODevice)硬件设备并非直接接入到总线上和CPU通信,而是通过接... 查看详情

如何使用 Node.js net.Socket 与 Postgresql 数据库进行通信,就像使用终端一样

】如何使用Node.jsnet.Socket与Postgresql数据库进行通信,就像使用终端一样【英文标题】:HowtoUseNode.jsnet.SocketToCommunicatewithPostgresqlDatabaseLikeOneWouldUsingTerminal【发布时间】:2016-06-0804:34:56【问题描述】:在postgresql终端中,我可以键入... 查看详情

一文搞懂uart通信协议

目录1、UART简介2、UART特性3、UART协议帧3.1、起始位3.2、数据位3.3、奇偶校验位3.4、停止位4、UART通信步骤1、UART简介UART(UniversalAsynchronousReceiver/Transmitter,通用异步收发器)是一种双向、串行、异步的通信总线,仅... 查看详情

一文搞懂uart通信协议

目录1、UART简介2、UART特性3、UART协议帧3.1、起始位3.2、数据位3.3、奇偶校验位3.4、停止位4、UART通信步骤1、UART简介UART(UniversalAsynchronousReceiver/Transmitter,通用异步收发器)是一种双向、串行、异步的通信总线,仅... 查看详情

从网络/TCP/HTTP 连接的角度来看,Node.js 是如何工作的? WCF 可以模拟这个吗?

】从网络/TCP/HTTP连接的角度来看,Node.js是如何工作的?WCF可以模拟这个吗?【英文标题】:HowdoesNode.jsworkfromanetwork/TCP/HTTPconnectionperspective?CanWCFemulatethis?【发布时间】:2011-07-1414:01:03【问题描述】:我的理解是node.js是一个面向Lin... 查看详情

一文搞懂仿射变换(代码片段)

导读在图像处理中,我们经常需要对图像进行各种操作如平移、缩放、旋转、翻转等,这些其实都是图像的仿射变换。通过本篇文章,你能够知道它们的实现原理以及如何应用它们。仿射变换仿射变换也称仿射投影&#x... 查看详情

一文搞懂tcp的三次握手和四次挥手(代码片段)

目录1、三次握手2、四次挥手3、11种状态名词解析TCP的三次握手和四次挥手实质就是TCP通信的连接和断开。三次握手:为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量... 查看详情

一文带你彻底搞懂docker中的cgroup(代码片段)

前言进程在系统中使用CPU、内存、磁盘等计算资源或者存储资源还是比较随心所欲的,我们希望对进程资源利用进行限制,对进程资源的使用进行追踪。这就让cgroup的出现成为了可能,它用来统一将进程进行分组࿰... 查看详情

一文搞懂如何在intellijidea中使用debug,超级详细!

https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485250&idx=1&sn=9e1f270996441094104a06fc909c60f5&chksm=cea24889f9d5c19fbc6024779ca476a3ee141efa457fc86cc8c33a8f06a1c2b1e7b4922 查看详情

一文搞懂│什么是跨域?如何解决跨域?

查看详情

一文搞懂kerberos

Kerberos1.Kerberos模型2.凭证3.协议Kerberos一词来源于古希腊神话中的Cerberus——守护地狱之门的三头犬,Kerberos是为TCP/IP网络设计的可信第三方鉴别协议,最初是在麻省理工学院(MIT)为Athena项目而开发的。Kerberos服务起着可信仲... 查看详情

深度分析springaop,一文带你彻底搞懂springaop底层原理!

SpringAOP我们为什么要使用AOP(面向切面编程)?当我们在现实中完成实际的项目时,我们总是需要在一个“动作”进行前,进行中,或进行后进行一些操作,比如当我们在运行程序时,我们想要进行日志保存,或者在每一个方法... 查看详情