简介
net
模块是nodejs
通讯功能实现的基础,nodejs
中最常用的功能就是作为WebServer使用,建立服务器时使用的http.createServer
就是在net.createServer
方法的基础上建立的。
前端最熟悉的http
协议属于应用层协议,应用层的内容想要发送出去,还需要将消息逐层下发,通过传输层(tcp
,udp
),网际层(ip
)和更底层的网络接口后才能被传输出去。net
模块就是对分层通讯模型的实现。
net
模块中有两大主要抽象概念——net.Server
和net.Socket
。
Socket
是对 TCP/IP 协议族的一种封装,是应用层与TCP/IP协议族通信的中间软件抽象层。它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
简单地说,net.Server
实例可以监听一个端口(用于实现客户端TCP
连接通讯)或者地址(用于实现IPC
跨进程通讯);net.Socket
实例可以建立一个套接字实例,它可以用来和server
建立连接,连接建立后,就可以实现通讯了。
使用示例
下面贴出UE4的pixelStreaming中MatchMaker的服务发现代码,以供参考:
// server
const net = require('net');
function disconnect(connection) {
console.log(`Ending connection to remote address ${connection.remoteAddress}`);
connection.end();
}
const matchmaker = net.createServer((connection) => {
///console.log(`Connection: ${JSON.stringify(connection)}`);
console.log(`-----------------Connection remote address ${connection.remoteAddress}`);
connection.on('data', (data) => {
try {
message = JSON.parse(data);
console.log(`> Recv Cirrus information from data: ${data.toString()}`);
} catch(e) {
console.log(`ERROR (${e.toString()}): Failed to parse Cirrus information from data: ${data.toString()}`);
disconnect(connection);
return;
}
if (message.type === 'connect') {
// A Cirrus server connects to this Matchmaker server.
cirrusServer = {
address: message.address,
port: message.port,
numConnectedClients: 0
};
cirrusServers.set(connection, cirrusServer);
console.log(`Cirrus server ${cirrusServer.address}:${cirrusServer.port} connected to Matchmaker`);
} else if (message.type === 'clientConnected') {
// A client connects to a Cirrus server.
cirrusServer = cirrusServers.get(connection);
cirrusServer.numConnectedClients++;
console.log(`Client connected to Cirrus server ${cirrusServer.address}:${cirrusServer.port}`);
} else if (message.type === 'clientDisconnected') {
// A client disconnects from a Cirrus server.
cirrusServer = cirrusServers.get(connection);
cirrusServer.numConnectedClients--;
console.log(`Client disconnected from Cirrus server ${cirrusServer.address}:${cirrusServer.port}`);
} else {
console.log('ERROR: Unknown data: ' + JSON.stringify(message));
disconnect(connection);
}
});
// A Cirrus server disconnects from this Matchmaker server.
connection.on('error', () => {
cirrusServers.delete(connection);
console.log(`Cirrus server ${cirrusServer.address}:${cirrusServer.port} disconnected from Matchmaker`);
});
});
matchmaker.listen(matchmakerPort, () => {
console.log('Matchmaker listening on *:' + matchmakerPort);
});
// client
if (config.UseMatchmaker) {
var matchmaker = new net.Socket();
matchmaker.on('connect', function () {
console.log(`Cirrus connected to Matchmaker ${matchmakerAddress}:${matchmakerPort}`);
message = {
type: 'connect',
address: typeof serverPublicIp === 'undefined' ? '127.0.0.1' : serverPublicIp,
port: httpPort
};
matchmaker.write(JSON.stringify(message));
});
matchmaker.on('error', (err) => {
console.log(`Matchmaker connection error ${JSON.stringify(err)}`);
});
matchmaker.on('end', () => {
console.log('Matchmaker connection ended');
});
matchmaker.on('close', (hadError) => {
console.log(`Matchmaker connection closed (hadError=${hadError})`);
reconnect();
});
// Attempt to connect to the Matchmaker
function connect () {
matchmaker.connect(matchmakerPort, matchmakerAddress);
}
// Try to reconnect to the Matchmaker after a given period of time
function reconnect () {
console.log(`Try reconnect to Matchmaker in ${matchmakerRetryInterval} seconds`)
setTimeout(function () {
connect();
}, matchmakerRetryInterval * 1000);
}
connect();
}
// The Matchmaker will not re-direct clients to this Cirrus server if any client
// is connected.
function sendPlayerConnectedToMatchmaker () {
if (!config.UseMatchmaker)
return;
message = {
type: 'clientConnected'
};
matchmaker.write(JSON.stringify(message));
}
// The Matchmaker is interested when nobody is connected to a Cirrus server
// because then it can re-direct clients to this re-cycled Cirrus server.
function sendPlayerDisconnectedToMatchmaker () {
if (!config.UseMatchmaker)
return;
message = {
type: 'clientDisconnected'
};
matchmaker.write(JSON.stringify(message));
}