Node.js TCP Server
TCP Server 通过 Node 中的 net
模块来实现 TCP 四层模型(应用层、传输层、网络层、链路层)
Id | Name | Info | Protocol |
---|---|---|---|
1 | 链路层(Link layer) | 负责在以太网、Wifi 底层网络发送数据包,并通过网卡、使用 MAC 地址来标记网络上的设备 | GPRS、IEEE、IPoe、Localhost、TRILL、IPoAC、FDDI、NAK\NACK、SEND、frame\frame relay、ATM、Data Link Layer、PPP、STP、L2TP、ARQ、CDPD、LLDP、LCP、Link Aggregation、HDLC |
2 | 网络层\网络互联层(Internet layer) | 定义了 IP 地址的概念,通过 IP 地址取代 MAC 地址,并将局域网、广域网链接成一个虚拟网络,主要目的就是 将 IP 地址翻译成 MAC 地址就可查找设备 | IPsec、IPv4\IPv5\IPv6\IPv9、 IP Address、x.25、IPX、ICMP\ICMPv6、IGMP、DDP、Mobile IP、Network Layer、PPP、RSVP、Anti-replay |
3 | 传输层(Transport layer) | 保证数据在 IP 地址标记的两点之间进行传输 | TCP、UDP、TLS\SSL、DCCP、SCTP、RSVP |
4 | 应用层(Application layer) | 直接与应用程序和接口结合,并提供常见的应用服务 | DHCP、DNS、FTP、gopher、HTTP\HTTP-2、IMAP4、IRC、NNTP、XMPP、POP3、SIP、SMTP、SNMP、SSH、TELNET、RPC、RTCP、RTP、RTSP、SDP、SOAP、GTP、STUN、NTP、SSDP |
对于每个网络层次,Node 都提供了相应的模块,如 http、net、tls/crypto、dgram 等,其中 net、http、dgram 模块分别实现和提供 TCP、HTTP 的通信,其中 http
为应用层模块,而 net
为传输层模块。
1 |
|
创建一个 TCP 服务可以通过 net.createServer
方法进行创建,可通过 server.listen
来设置服务的监听端口以及,当然一旦运行服务时除发的还是 server 下的 listening
事件,因此也支持另一种写法:
net.Server()
1 | var net = require('net') |
除此之外 server
还支持另外几种 TCP 事件:
Id | Name | Info |
---|---|---|
1 | listening | 调用 server.listen(),即当开始监听时候除发 |
2 | connection | 当有新创建时后除发,回调的参数是 socket 连接的对象 |
3 | close | 当关闭时触发,回调函数没有参数 |
4 | error | 当 TCP 服务发生错误时触发,回调参数为 error |
1 | var net = require('net') |
server.address()
如果需要监听 IP 套接字,也就是套接字地址(socket address),可以通过 server.address()
方法来实现,他主要提供了三个服务器绑定的 address
以及 family
和 port
1 | var net = require('net') |
需要注意的是如果监听的端口号是 IPv6 地址,那么
address
则返回::
server.getConnections()
.server.getConnections
方法用于异步获取服务器上的并发连接数,回调参数分为 err
和 count
1 | const net = require("net") |
之后我们分别通过 GET 请求 http://127.0.0.1:8210/ 并通过代理访问 uri 则有三个 IP 访问,因此分别依次循环输出 This is Client count: 1~3
Server at Client 之间的通信
Server
服务端主要用于接收客户端所发送的消息,因此只需要通过 data
事件来接收数据时进行输出,在收到数据之前首先通过 address()
来将转换为 JSON
格式并输出,并通过 socket.bytesWritten
来计算客户端所发送的字节数,最后通过 socket.bytesRead
方法来统计书数据的大小。
1 | const net = require('net') |
Client
在 Server 与 Client 建立链接的过程中,客户端扮演的是数据发送者的身份,而他主要的作用就是与服务端建立链接并发送数据,之后监听服务端的状态,在这期间主通过 client.connect
来链接服务,之后使用其 client.write
来写入数据并发送。
net.Socket 类
API
对于 net.Socket
相关的 API Node 提供了多种方法:
Id | Name | Info |
---|---|---|
1 | socket.address() | 返回操作系统报告并绑定 address,和套接字的 port 以及 family 等 |
2 | socket.bytesRead() | 接收的字节数 |
3 | socket.bytesWritten() | 发送的字节数 |
4 | socket.connect(options[,sonnectListener]) | 指定套接字链接 |
options | ||
port 套接字应该链接到的端口(必填) |
||
host 套接字应连接到的主机(默认为 localhost ) |
||
localAddress 套接字应该链接到本地地址 |
||
localPort 套接字应链接本地端口 |
||
family IP 堆栈的版本(通常是 IPv6、IPv4或0,而 0 表示 允许 IPv4/6 地址) |
||
hints 可选的 dns.lookup() 提示(主机名) |
||
lookup 自定义查找函数(默认 dns.lookup() ) |
||
5 | socket.connect(port[,host][,connectListener]) | 指定套接字链接 |
port 客户端应该链接到的端口 |
||
host 客户端应该链接到的主机 |
||
connectListener 方法的常用参数,将被添加为 connect 事件监听 |
||
6 | socket.destroyed 半关闭套接字,服务端关闭时发送数据包给客户端,客户端关闭 |
|
7 | socket.localAddress | 远程客户端链接本地 IP 地址(以 IP 地址的字符串形式表示,如 0.0.0.0 ) |
8 | socket.localPort(socket.remotePort) | 本地端口数字表示(如 8210 ) |
9 | socket.remoteAddress | 远程 IP 地址的字符串形式输出(如 74.125.127.100 或 2001:4860:a005::68 ) |
10 | socket.remoteFamily | 远程 IP 系列的字符串形式表示(如 IPv6 或 IPv4 ) |
11 | socket.setTimeout(socket.timeout) | 用于进行设置连接(如果 timeout 为 0,则禁用空闲超时) |
12 | socket.setKeepAlive() | 用于设置和i长连接 |
13 | socket.destroy()\socket.destroyed | 当错误发生时,用于销毁 socket,以确保这个 socket 上不会有其他 IO 操作 |
事件
Id | Name | Info |
---|---|---|
1 | close | 当链接断开时触发,假设因为传输错误导致断开,则参数为 err |
2 | connect | 当建立成功套接字链接时触发 |
3 | data | 接收到数据时触发 |
4 | drain | 当写缓存空了时触发 |
5 | end | 当另一端结束时触发 |
6 | error | 当错误时触发 |
7 | lookup | 当解析完主机名后触发 |
8 | ready | 当套接字准备好使用时触发 |
9 | timeout | 提示用户 socket 超时,需要手动关闭链接 |
1 | const net = require('net') |