在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端口对象
- options: 对象;可以在该对象中使用一个布尔类型的allowHalfOpen属性
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: 发送者所发送的数据的字节数
- 回调函数中,可以使用2个参数,msg:值为一个Buffer对象,存放接收的数据;rinfo参数值是一个对象,该对象所具有的属性及属性值如下:
创建简单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 小结
- 没有小结