zoukankan      html  css  js  c++  java
  • 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 模块中的类和方法

  • 相关阅读:
    Linux知识(4)----文件系统结构
    ROS知识(4)----初级教程之常见问题汇总
    Linux知识(3)----常用快捷键和命令
    ROS知识(1)----ROS Jade安装
    Linux知识(1)----U盘安装Ubantu14.04系统
    Linux知识(2)----中文输入法安装
    EM(Expectation Maximization)算法
    idea xml 绿背景色 去掉拼写检查
    Java transient
    java代码中获取classpath路径
  • 原文地址:https://www.cnblogs.com/luwei0915/p/14081935.html
Copyright © 2011-2022 走看看