07_TCP 与 UPD 的通信

7.1 TCP链接

i> TCP服务器 与 socket 端口对象

var net = require('net');
var file = require('fs').createWriteStream('./a.txt');

// 或者 server = net.createServer((socket) => {})
var server = net.createServer();

server.maxConnections = 10;
// 设置TCP最大连接数
console.log('TCP服务器的最大连接个数为:%d', server.maxConnections);

server.on('connection', (socket) => {
    console.log('客户端与服务端链接已建立');

    address = socket.address();
    // 新客户端连上时显示,用来读取客户端发送的流数据
    console.log('socket端口对象的地址信息是%j', address);
    // socket端口对象的地址信息是{"address":"127.0.0.1","family":"IPv4","port":999}

    socket.setEncoding('utf8');
    // 连接上,发送什么,可以实时接收到
    socket.on('data', (data) => {
        // 设置了 setEncoding,否则 console.log(data.toString());
        console.log(data);
        console.log('已经接收到%d字节的数据', socket.bytesRead);
    });

    // 暂停 socket 的 data 事件的触发,此时数据暂存在一个单独的缓存区中
    // 激活是 socket.resume();
    // 作用是限制对某个或多个客户端的读取速度,只是暂时放在一个单独的缓存区中
    socket.pause();

    // 将客户端传入的数据写入到文件 socket 对象的 pipe方法
    // 当客户端主动断开时,可以先不关闭,等着触发一个 end 事件
    // 取消写入是 socket.unpipe(file)
    socket.pipe(file, { end: false });

    // 客户端主动关闭
    socket.on('end', () => {
        console.log('客户端连接被关闭');
        // 触发该 end 事件
        file.end('再见');
    });

    socket.setTimeout(10 * 1000);
    socket.on('timeout', () => {
        console.log('10秒内无新的交互,已超时');
        // 既只执行一次 取消再次触发该事件
        socket.setTimeout(0);
    });
});

server.getConnections((err, count) => {
    console.log('当前存在%d个客户端连接', count);
});

// error 是写死的
server.on('error', (e) => {
    if (e.code == 'EADDRINUSE') {
        console.log('服务器地址和端口被占用');
    };
});

server.close(() => {
    console.log('TCP服务器被关闭');
});

// 此时可以 telnet 127.0.0.1 999 连接测试
server.listen(999, '127.0.0.1', () => {
    console.log('服务器开始监听');
    address = server.address();
    console.log('被监听的地址信息为:%j', address);
    // 被监听的地址信息为:{"address":"127.0.0.1","family":"IPv4","port":999
});

i> 创建TCP客户端

 服务端:

var net = require('net');
var server = net.createServer();
var fs = require('fs');

// 建立TCP服务器
server.on('connection', (socket) => {
    console.log('客户端与服务端连接已建立');
    socket.setEncoding('utf8');

    socket.setKeepAlive(true, 5000);

    // 将文件内容发送过去
    // readStream 读取文件流,将读取的内容放到队列缓冲区中
    // 然后 socket.write 从队列缓冲区中拿数据发送
    var readStream = fs.createReadStream('./a.txt');
    readStream.on('data', (data) => {
        var flag = socket.write(data);
        // 如果一次性发不完,则 flag 为 false,否则为 true
        console.log('发送文件内容的返回值' + flag);
        console.log('缓存队列缓存了%d字节的字符', socket.bufferSize);
    });

    // 每当有新的连接进来,都会执行这里
    // 当前接收的客户端连接数为2时,拒绝新的客户端请求
    server.getConnections((err, count) => {
        console.log('现在客户端连接数量是:%d', count);
        if (count == 2) server.close();
        // 与服务器连接发生了错误,错误码为ECONNREFUSED
    });

    socket.on('data', (data) => {
        console.log('接收到客户端发送的数据:' + data);
        // socket.write('你好,Client');
    });


    // 缓冲区 有数据 => 没数据
    socket.on('drain', () => {
        console.log('TCP缓冲区的数据已经全部发送');
    });

    // 客户端 crtl + c 掉
    socket.on('error', (err) => {
        console.log('与客户端通信发生了一个错误,错误码是:%s', err.code);
        // 与客户端通信发生了一个错误,错误码是:ECONNRESET

        // destroy 销毁端口对象,确保端口不会再被利用
        socket.destroy();
        server.close();
    });

    // 客户端调用了 end 方法主动关闭之后
    // 此时 服务端仍然未关闭
    socket.on("end", () => {
        console.log('客户端连接被关闭');

        // 自己也主动关闭
        // 之后也可以用,server.ref() 方法阻止应用程序的关闭
        server.unref();
    });


    // 试着打开/ 关闭 客户端的 end事件,使用 ctrl + c 查看
    // 如果客户端自己正常 end ,则不会有 had_error 错误
    socket.on('close', (had_error) => {
        if (had_error) {
            console.log('由于一个错误导致socket端口被关闭');
            socket.unref();
        } else {
            console.log('socket端口正常关闭');
        }
    });
});


server.on('close', () => {
    console.log('关闭TCP服务器');
});

server.listen(999, '127.0.0.1');

客户端:

var net = require('net');
var client = new net.Socket();
client.setEncoding('utf8');

// TCP 客户端
client.connect(999, '127.0.0.1', () => {
    console.log('已经连接到服务端');
    client.write('你好,Server');
    console.log('当前已经发送%d字节的数据', client.bytesWritten);

    setTimeout(() => {
        // end 方法关闭与服务端的链接
        client.end('10秒后我主动断开,再见');
        console.log('当前已经发送%d字节的数据', client.bytesWritten);
    }, 10 * 1000);
});

client.on('data', (data) => {
    console.log('收到服务端发送的数据:' + data);
});

client.on('error', (err) => {
    console.log('与服务器连接发生了错误,错误码为%s', err.code);
    client.destroy();
});

i> net 模块中的类和方法

原文地址:https://www.cnblogs.com/luwei0915/p/14081935.html