06-网络 TCP-net

109 阅读4分钟

网络 TCP-net

模块概览
net模块同样是nodejs的核心模块.在http模块概览里提到,http.server继承了net.server,此外,http客户端与http服务器的通信依赖于socket(net.Socket),也就是说,做node服务器编程,net
net.server: TCP server, 内部通过socket来实现与客户端的通信
net.socket: TCP/本地 socket的node版实现, 他实现了全双功的stream接口

简单的 server+client 例子

const PORT = 3000;
const HOST = "127.0.0.1";

// tcp服务器
const server = net.createServer((socket) => {
  console.log("服务端: 接收到来自客户端的信息");
  socket.on("data", (data) => {
    console.log("服务端收到客户端的内容为:", data);
    socket.write("你好. 我是服务端");
  });
  socket.on("close", () => {
    console.log("服务端: 客户端断开连接");
  });
});
server.listen(PORT, HOST, () => {
  console.log("服务端:开始监听来自客户端的请求");
});

// tcp客户端
const client = net.createConnection(PORT, HOST);
client.on("connect", () => {
  console.log("客户端: 连接成功");
});
client.on("data", (data) => {
  console.log("客户端:接收到服务端的数据", data);
});
client.on("close", () => {
  console.log("客户端:断开连接");
});
client.end("你好 我是客户端");

// 服务端:开始监听来自客户端的请求
// 客户端: 连接成功
// 服务端: 接收到来自客户端的信息
// 服务端收到客户端的内容为: <Buffer e4 bd a0 e5 a5 bd 20 e6 88 91 e6 98 af e5 ae a2 e6 88 b7 e7 ab af>
// 客户端:接收到服务端的数据 <Buffer e4 bd a0 e5 a5 bd 2e 20 e6 88 91 e6 98 af e6 9c 8d e5 8a a1 e7 ab af>
// 服务端: 客户端断开连接
// 客户端:断开连接

服务端 net.server

server.address()

返回服务端的地址信息, 比如绑定的ip地址和端口等;

const server = net.createServer();
server.listen(3000, "127.0.0.1", () => {});

server.close(callback)

关闭服务器,停止接受新的客户端的请求,有几点注意事项
1.对正在处理的请求,服务器会等待他们处理完(或超时),然后在进行正式的关闭
2.正常关闭的同时,callback会被执行,同时出发close的方法
3.异常关闭的同时,callback也会执行,同时将对应的error作为参数传入(比如在没有调用server.listen(port)的之前,就调用了server.close())
结论:
1.已经调用server.listen():正常关闭,close事件触发,然后callback执行,error参数为undefined
2.没有调用server.listen():异常关闭,close事件触发,然后callback执行,error为具体的错误信息(注意:error事件没有触发)

例子:服务端正常关闭
  const PORT = 3000
  const HOST = '127.0.0.1'
  const server = net.createServer(() => { })
  server.listen(PORT, HOST, () => {
    server.close((error) => {
      if (error) {
        console.log('close回调:服务端异常', error.message);
      } else {
        console.log('close回调:服务端正常关闭')
      }
    })
    server.on('close', () => {
      console.log('close事件:服务端关闭');
    })
    server.on('error', error => {
      console.log('error事件: 服务端异常', error.message);
    })
  })
// close回调:服务端正常关闭
// close事件:服务端关闭

例子:服务端异常关闭
  const PORT = 3000
  const HOST = '127.0.0.1'
  const server = net.createServer(() => { })
  server.close((error) => {
    if (error) {
      console.log('close回调:服务端异常', error.message);
    } else {
      console.log('close回调:服务端正常关闭')
    }
  })
  server.listen(PORT, HOST, () => {
    server.on('close', () => {
      console.log('close事件:服务端关闭');
    })
    server.on('error', error => {
      console.log('error事件: 服务端异常', error.message);
    })
  })
// close回调:服务端异常 Server is not running.

server.ref() server.unref()

主要用于将server 加入事件循环/从事件循环里面移除, 影响就在于会不会影响进程的退出

listening/connection/close/error

listening调用server.listen()正式开始监听请求的时候触发
connection当有新的请求进来饿时候触发,参数为请求相关的socket
close服务端关闭的时候触发
error服务出错的时候触发,不如监听了已经被占用的端口

举例connection
  const PORT = 3000
  const HOST = '127.0.0.1'
  const server = net.createServer(socket => {
    socket.write('1. connection触发')
  })
  server.on('connection', socket => {
    socket.end('2. connection触发')
  })
  server.listen(PORT, HOST)

// 1. connection 触发
// 2. connection 触发

客户端 net.socket

单从node官方文档来看,
  node.socket比node.server要复杂的多,
  有更多的API,
  事件,
  属性.实质上,
  把net.socket相关的api,
  事件,
  属性进行归类后发现,
  也并不是很复杂;
const PORT = 3000;
const HOST = "127.0.0.1";
const client = net.createConnection(POST, HOST);
client.on("connect", () => {
  console.log("客户端:已经和服务端建立连接");
});
client.on("data", (data) => {
  console.log("客户端:收到服务端的数据", data);
});
client.on("close", (data) => {
  console.log("客户端:连接断开");
});
client.end("你好 我是客户端");

API, 属性归类

连接相关
socket.connect()  有三种不同的参数用于不同的场景
socket.setTImeout() 用来进行连接超时的设置
socket.setKeepAlive() 用来设置长链接
socket.destroy()  socket.destroyed 当错误发生时,用来销毁socket,确保这个socket上不会再有其他的IO操作

数据读写相关

socket.write();
socket.end();
socket.pause();
socket.resume();
socket.setEncoding();
socket.setNoDelay();

数据属性相关

socket.bufferSize;
socket.byteRead;
socket.byteWritten;

事件循环相关

socket.ref();
socket.unref();

地址相关

socket.address();
socket.remoteAddress;
socket.remoteFamily;
socket.remotePort;
socket.localAddress / socket.localPort;

事件简介

data 当收到另一侧传来数据的时候触发
connect 当连接建立的时候触发
close  连接断开的时候触发,如果因为传输错误导致的连接断开,则蚕食error
end 当连接另一侧发送了FIN包的时候触发,默认情况下(allowHalfOpen==false),socket会完成自我销毁操作,但你也可以把allowHalfOpen设置为true,这样就可以继续往socket里写数据,当然,最后你需要手动调用socket.end()
error 当有错误发生时,就会触发,参数为error,
timeout 提示用户,socket已经超时,需要手动关闭连接
drain  当写缓存空了的时候触发,
lookup 域名解析完成触发