在Node.js中,提供了一个net模块与一个dgram模块,分别用于实现基于TCP的数据通信以及基于UDP的数据通信

  • 创建TCP服务器
  • 使用TCP服务器监听客户端连接的socket端口对象读取客户端发送的数据
  • 创建TCP客户端以及利用客户端用于连接TCP服务器的socket端口对象向客户端发送数据
  • 创建UDP服务器与UDP客户端,实现UDP客户端与UDP服务器之间的通信
  • 从UDP服务器向客户端广播数据,从UDP服务器向客户端组播数据

1 使用net模块实现基于TCP的数据通信

1.1 创建TCP服务器

  • 在node.js中,可以很方便地创建一个TCP服务器,只需要调用net模块的createServer方法
var server = net.createServer([options], [connectionListener])
  • 可选参数:

    • options: 对象;可以在该对象中使用一个布尔类型的allowHalfOpen属性
      • false: 当TCP服务器接收到客户端发送的一个FIN包时将会回发一个FIN包
      • true:TCP服务端接收到客户端发送的FIN包时不回发FIN包,TCP继续向客户端发送数据,当不再继续接收客户端发送的数据。开发者必须调用end方法来关闭socket连接
      • allowHalfOpen默认属性为false
    • connectionListener: 指当客户端与服务端建立连接时所调用的回调函数
    function (socket) {
        // 回调函数代码
    }
    
    • 在该回调函数中使用一个参数,参数值为该TCP服务器监听的socket端口对象
server.on('connection', function (socket) {
    // 回调函数代码
})
  • 在创建TCP服务器之后,使用listen方法通知服务器开始监听客户端连接
// 方法一
server.listen(port, [host], [backlog], [callback])

// 方法二
server.listen(path,[callback])

// 方法三
server.listen(handle, [callback])

// 其他
server.on('listening', function() {
    // 回调函数
})
  • 一个简单的实例:
var net = require('net');
var server = net.createServer(function(socket) {
    console.log('客户端与服务端连接已建立')
});

server.listen(8431, 'localhost');
server.on('error', function (e) {
    if (e.code == 'EADDRINUSE') {
        console.log('服务器地址及端口已被占用');
    }
});

var address = server.address();
console.log(address) // 返回一个对象:port, address,family
  • TCP服务器的getConnections():查看当前与TCP服务器建立连接的客户连接数量
    • server.getConnections(callback): 异步方法
// 使用getConnections方法查询当前存在的客户端连接数
var net = require('net');
var server = net.createServer(function(socket) {
    server.getConnections(function(err, count){
        console.log('当前存在%d个客户端连接', count);
        server.maxConnections = 2;
        console.log('TCP服务器的最大连接数为%d', server.maxConnections);
    });
})
server.listen(8431, 'localhost');
    console.log('TCP服务器被创建');
  • 最后使用TCP服务器的close方法显式指定服务器拒绝所有的新客户端连接
    • server.close([callback])
// 使用close方法拒绝新的客户连接请求
var net = require('net');
var server = net.createServer(function(socket) {
    server.close(function () {
        console.log('TCP服务器被关闭');
    })
});
server.listen(8431, 'localhost');

1.2 socket端口对象

使用net.Socket代表一个socket端口对象

  • var address = socket.address()
// 实例
// 使用socket端口对象的address()来查看端口地址信息
var net = require('net');
var server = net.createServer();
server.on('connection', function(socket) {
    address = socket.address();
    console.log('socket端口对象的地址信息为%j', address);
});
server.listen(8431, 'localhost');
  • data事件的回调函数的使用示例
var net = require('net');
var server = net.createServer();
server.on('connection', function(socket) {
    socket.on('data', function (data) {
        console.log(data);
    });
})

server.listen(8431, 'localhost');
  • end事件的回调函数
var net = require('net');
var server = net.createServer();
server.on('connection', function(socket) {
    socket.setEncoding('utf8');
    socket.on('data', function(data) {
        console.log(data);
        console.log('已收到%d字节数据。', socket.bytesRead);
    });
    socket.on('end', function () {
        console.log('客户端连接被关闭')
    })
})
server.listen(8431, 'localhost');
  • 使用pipe方法将所有客户端发送数据写入文件
var net = require('net');
var file = require('fs').createWriteStream('./message.txt');
var server = net.createServer();
server.on('connection', function(socket) {
    socket.pipe(file);
});
server.listen(8431, 'localhost');
  • 当socket端口对象的pipe方法的options参数对象中使用end属性值且值设置为false时,当客户端不会再发送新的数据时,不会立即结束目标对象的写操作,可以再目标对象中补充写入一些数据。
server.on('connection', function(socket) {
    socket.pipe(file, {end:false});
    socket.on('end', function () {
        file.end('再见了您');
    })
})
  • socket端口对象的pause方法与resume方法
var net = require('net');
var file = require('fs').createWriteStream('/message.txt');
var server = net.createServer();

server.on('connection', function(socket) {
    socket.pause();
    setTimeOut(fucntion() {
        socket.resume();
        socket.pipe(file);
    }, 30000);
});
server.listen(8431, 'localhost');
  • 取消对客户端连接的超时时间的指定
var net = require('net');
var server = net.createServer();
server.on('connectiion', function(socket {
    socket.setTimeout(10*1000);
    socket.on('timeOut', fucntion() {
        console.log('客户端连接已超时');
        socket.setTimeOut(0);
    })
})
server.listen(8431, 'localhost');

1.3 创建TCP客户端

在node.js中,创建TCP客户端简单,只需要创建一个用于连接TCP服务器的socket端口对象即可

var net = new net.Socket([options]);
  • options参数

    • fd: 用于指定一个现存的socket的文件描述符,TCP客户端将使用这个现存的socket端口与服务器端相连接。
    • type: 用于指定客户端所使用协议,可指定值为“tcp4”, “tcp6”,“unix”
    • allowHalfOpen: 该属性值被指定为false时,当TCP服务器接收到客户端发送的一个FIN包时将会回发一个FIN包,当该属性值被设定为true时,当TCP服务器接收到客户端发送的一个FIN包时不回发FIN包,这使得TCP服务器可以继续向客户端发送数据,但是不会继续接收客户端发送的数据。开发者必须调用end方法(稍后介绍)来关闭该socket连接。该属性的默认属性值为false
  • 创建socket端口对象后,连接TCP服务器的方法:

    • socket.connect(port, [host], [connection])
    • socket.connect(path, [connectListener])
      • 这种形式的connect方法用于与一个使用unix端口的服务器进行连接
  • 创建TCP客户端

var net = require('net');
var client = new net.Socket();
client.setEncoding('utf8');
client.connect(8431, 'localhost', function() {
    console.log('已连接到服务器');
    client.write('你好啊');
});

client.on('data', function(data) {
    console.log('已接收服务端发送的数据:', data);
})
  • 创建TCP服务器
var net = require('net');
var server = net.createServer();
server.on('connection', function(socket) {
    console.log('客户端与服务端连接已建立');
    socket.setEncoding('utf8');
    socket.on('data', function(data) {
        console.log('已接收客户端发送的数据:'+ data);
        socket.write('确认数据:' + data);
    })
})
server.listen(8431, 'loccalhost');
  • 使用TCP服务器对象的close方法拒绝新的客户端连接请求
var net = require('net');
var server = net.createServer();
server.on('connection', function(socket) {
    console.log('客户端与服务端连接已建立');
    socket.setEncoding('utf8');
    socket.on('data', function(data) {
        socket.write('确认数据:'+data);
    });
    socket.on('error', function(err) {
        console.log('与客户端通信得过程中发生一个错误,错误编码%s', err.code);
        socket.destory();
    });
    socket.on('end', function() {
        console.log('客户端连接被关闭');
        server.unref();
    });
    socket.on('close', function(had_error) {
        if(had_error) {
            console.log('由于一个错误导致socket端口被关闭');
            server.unref();
        } else {
            console.log('socket端口被正常关闭')
        }
    });
    server.getConnections(function(err, count) {
        if(count == 2) {
            server.close();
        }
    })
})

server.listen(8431, 'localhost');
server.on('close', function() {
    console.log('TCP服务器被关闭');
});

1.4 net模块中的类方法

  • isIP()

    • 用于判断一个字符串值是否为一个IP地址
    • net.isIP(input)
    • 返回值:不是IP,返回0;IPV4,返回4;IPV6,返回6;
  • isIPv4()

    • 返回true,false
  • isIPv6()

    • 返回boolean值

2 使用dgram模块实现基于UDP的数据通信

TCP是一种基于连接的协议,在进行通信前,首先要求客户端与服务端建立一条用于通信的连接。 UDP是一种面向非连接的协议,在进行通信前,不要求首先建立客户端与服务端之前的连接,可以直接把数据包发送给对方。 UDP是一种不可靠的协议,当传输速度比TCP更快,更适用于实时通信的场合

node.js中提供了dgram模块,用于创建UDP服务器与客户端,以实现UDP服务器与客户端之间的通信

2.1 创建UDP服务器与客户端

var socket = dgram.createSocket(type, [callback])
  • 在createSocket方法中,可以使用2个参数:

    • type: 指定进行UDP通信时使用的协议类型,可指定为"udp4"或"udp6"
    • callback: 回调函数
      • 回调函数中,可以使用2个参数,msg:值为一个Buffer对象,存放接收的数据;rinfo参数值是一个对象,该对象所具有的属性及属性值如下:
        • address: 发送者所使用的地址
        • family: 发送者所使用的地址是IPv4还是IPv6
        • port: 发送者所使用的socket端口号
        • size: 发送者所发送的数据的字节数
  • 创建简单UDP服务器

var dgram = require('dgram');
var server = dgram.createSocket("udp4");
server.on("message", function (msg, rinfo) {
    console.log('已接收客户端发送的数据:'+ msg);
    console.log("客户端地址信息为%j", rinfo);
    var buf = new Buffer("确认信息:"+msg);
    server.send(buf,0,buf.length,rinfo.port,rinfo.address);
});

server.on("listening", function () {
    var address = server.address();
    console.log("服务器开始监听。地址信息为%j", address);
});
server.bind(41234, 'localhost');
  • 创建简单UDP客户端
var dgram = require('dgram');
var message = new Buffer("你好。");
var client = dgram.createSocket("udp4");
client.send(message, 0, message.length, 41234, "localhost", function(err, bytes) {
    if(err) console.log("发送数据失败");
    else console.log("已发送%d字节数据。", bytes);
});

client.on("message", function (msg, rinfo) {
    console.log("已接收服务端发送得数据:%s", msg);
    console.log("服务器地址为%s", rinfo.address);
    console.log("服务器所用的端口为%s", rinfo.port);
})

2.2 实现广播与组播

  • socket.setBroadcast(flag)
    • setBroadcast(),使用一个布尔类型的参数,当参数值为true时,UDP服务器或客户端可以利用其所用的socket端口对象的send方法来进行数据的广播。
var dgram = require("dgram");
var server = dgram.createSocket("udp4");
server.on("message", function (msg) {
    var buf = new Buffer("已接受客户端发送的数据:", msg);
    server.setBroadcast(true);
    // 在本例中,客户端将端口号指定为41235
    server.send(buf, 0, buf.length, 41235, "192.168.1.255");
});
server.bind(41234, '192.168.1.100');

3 小结

  • 没有小结