• 基于node的tcp客户端和服务端的简单通信


    1.简单介绍下TCP/IP

    TCP/IP是互联网相关协议的集合,分为以下四层:应用层、传输层、网络层、数据链路层。

    分成四层的好处是,假如只有一层,某个地方需要改变设计时,就必须把所有整体替换掉,而分层之后只需把变动的层替换掉即可。

    2. 服务端编程

    node提供了net模块来实现tcp编程。主要分为服务端编程和客户端编程两部分,先来写服务端的:

    监听客户端连接

    先引入net模块,再通过 net.createServer 创建一个TCP服务器,服务器可以监听一个connection事件。

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

    • options<Object>

      • allowHalfOpen<boolean> 表明是否允许半开的 TCP 连接。默认值: false
      • pauseOnConnect<boolean> 表明是否应在传入连接上暂停套接字。默认值: false
    • connectionListener<Function> 自动设置为 'connection' 事件的监听器

    我们先不传参数:

    复制代码
    var net = require('net');
    //创建tcp服务器
    var server = net.createServer(); 
    
    //监听connect事件
    server.on('connection', (socket) => {
        socket.on('data',(data)=>{
            console.log(data.toString(), 'data')
        })
    })
    
    //设置监听端口
    server.listen(8989);
    
    //设置监听时的回调函数
    server.on('listening', (res)=>{
        console.log('in listen...')
    })
    复制代码

    connection事件当有数据发送过来时会被触发。监听函数的参数是一个socket,用户可以使用它与客户端进行交互。

    通过socket的data事件可以打印出发送过来的数据,在浏览器中打开 http://localhost:8989,浏览器会将请求头的信息发送到server,所以输出结果如下:

     上面代码中,connection事件可以传入到createServer中,listen和listening可以合并,写成下面这种形式:

    复制代码
    //第二种写法
    var net = require('net');
    //创建tcp服务器
    var server = net.createServer((socket) => {
        socket.on('data', (data) => {
            console.log(data.toString(), 'data..')
        })
    });
    //设置监听端口
    server.listen(8989, (res) => {
        console.log('in listen...')
    });
    复制代码

    除了listening和connect事件外,server还有如下事件:

    • close:TCP服务器关闭的时候触发,回调函数没有参数
    • error:TCP服务器发生错误的时候触发,回调函数的参数为error对象

    接收数据和发送数据

    通过socket的data事件接收数据,write方法发送数据

    socket.write(data[, encoding][, callback])

    复制代码
    //创建一个TCP服务器
    var server = net.createServer((socket) => {
        //'connect'事件的回调函数
        console.log('客户端已连接');
        socket.on('end', () => {
            console.log('客户端已断开');
        })
        //接收来自客户端的数据
        socket.on('data', (data) => {
            console.log(data.toString(), 'data');
            var readSize = socket.bytesRead;
            console.log('the size of data is ' + readSize);
        })
    
        //向客户端写入数据
        socket.write('hello\r\n');
    
        //设置连接最大数量,可不设
        server.maxConnection = 3;
    
        server.getConnections(function (err, count) {
    
            console.log('the count of clieent is ' + count);
    
        });
    
    })
    
    server.listen(8989, () => {
        console.log('服务器已启动');
        //获取地址信息
        var address = server.address();
    
        //获取地址端口
        console.log('the port of server is ' + address.port);
        console.log('the address of server is ' + address.address);
        console.log('the ip family of server is ' + address.family);
    })
    复制代码

    我们先不写客户端的代码,先用telnet工具来当作客户端来测试上面代码

    打开命令行工具输入 telnet localhost 8989

     

     可以看到  socket.write('hello\r\n') 这句话已经生效了,服务端向客户端返回了hello,但这样肯定还不够,

    3. 客户端编程

    客户端编程比服务端简单,因为不用监听端口。只要把数据从指定的端口发出去就可以了。

    net.createConnection(options[, connectListener]) 用来创建一个socket。第一个参数必填,要写发送的端口号,第二个参数是这个socket的 'connect'事件的回调函数

    复制代码
    //创建一个客户端
    var client = net.connect({ port: 8989 }, () => {
        console.log('连接到服务器');
        //向服务端发送数据
        client.write('hello,i am from client');
    })
    
    //监听事件,当服务端发送数据过来时会触发该事件
    client.on('data', (data) => {
        console.log(data, 'data');
        client.end()
    })
    
    client.on('end', () => {
        console.log('已从服务器断开');
    });
    复制代码

     上面代码的client就是一个socket,所以可以监听data事件来获取服务端发送来的数据。然后socket也可以通过write来向服务端发送数据

    4. 一个小的登录系统

    利用上面的知识,可以实现一个小型的登录系统:

    复制代码
    /*server.js*/
    var net = require('net');
    //这儿用一个对象来模拟数据库,保存用户名和密码
    var user = {
        admin: '123',
        test: '333',
        lucy: '222',
    }
    //临时变量保存用户输入的内容
    var username = '';
    
    var server = net.createServer((socket)=>{
        console.log('服务器已连接');
        socket.write('请输入用户名:');
        socket.on('data',(data)=>{
            //通过stdin输入的内容是buffer,需要转成字符串且清除空格
            data = data.toString().trim();
            if(!username){
                if(user[data]){
                    socket.write('请输入密码:');
                    username = data;
                }else{
                    socket.write('用户名不对,请输入用户名:');
                }
            }else {
                if(user[username] === data){
                    socket.write('登录成功');
                }else {
                    socket.write('密码不对,请输入密码:');
                }
            }
        });
        socket.on('close',data=>{
            console.log(data);
        })
    })
    
    server.listen(8899,()=>{
        console.log('服务器监听8899端口中')
    })
    复制代码
    复制代码
    /*client.js*/
    var net = require('net');
    process.stdin.resume(); 
    
    var client = net.createConnection({port: 8899},()=>{
        //process.stdin可以获取到用户的输入
        process.stdin.on('data',input=>{
            client.write(input)
        })
    })
    
    //这儿接收服务端的返回数据
    client.on('data',data=>{
        console.log(data.toString());
        if(data.toString()==='登录成功'){
            process.exit();
        }
    })
    复制代码

     

     

  • 相关阅读:
    Unity开发一个FPS游戏之三
    python 获取视频时长
    mysql 忘记密码后重置
    day03_基础语法
    【力扣】283. 移动零
    markdown希腊字母
    微前端原理解析
    git log
    vue配置@路径
    uniapp打包安卓apk的隐私政策配置
  • 原文地址:https://www.cnblogs.com/soraly/p/12163083.html