创建服务端
const server = net.createServer(); //HACK 返回net.Server
创建客户端
//HACK 返回net.Server
// socket是双工的 指的是A ——- B之间的连接. 如果有100个客户端 就会建立100个socket
const socket = net.createConnection({ host: HOST, port: PORT }, async () => {
console.log('connected to the server!');
用nodejs读取命令行界面(TTY模块,readline模块) 然后写到socket中
- 用nodejs readline读取命令行界面
const net = require('net');
const readline = require('readline/promises'); //提供接口读取readable stream中的内容
const PORT = 3099;
const HOST = '127.0.0.1';
// 用nodejs readline读取命令行界面
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
// process.stdin返回一个双工的流 可读的stream
});
- 写到socket中 这里的ask方法就是在终端给用户提示,让用户输入
const socket = net.createConnection({ host: HOST, port: PORT }, async () => {
console.log('connected to the server!');
const ask = async () => {
const message = await rl.question('Enter a message > ');
socket.write(`-${message}`);
};
ask();
socket是双工的 指的是A ——- B之间的连接. 如果有100个客户端 就会建立100个socket 可以用数组存储起来 让每个客户端都能收到彼此的信息。
而且我们要知道谁发送了这个信息?就要为连接到的每个客户端分配id
为连接到的每个客户端分配id
server.js
// 如果有100个客户端 就会建立100个socket 可以用数组存储起来 让每个客户端都能收到彼此的信息
const clients = [];
server.on('connection', (socket) => {
console.log('A new Connection to the server');
// 谁发送了这个信息?为连接到的每个客户端分配id
const clientId = clients.length + 1;
// 同时广播它的id
clients.map((client) => {
client.socket.write(`User ${clientId} joined`); //这个是在所有的客户端都会收到的:除了刚刚加入的这台客户端它自己不会收到 广播
});
// 告诉客户端被分配到了哪个id
socket.write(`id-${clientId}`); //这个和上面的有什么差别 这个是没有写到client的socket里面的 //这个只会在建立连接的socket收到
// 有客户端连接就把他的id和socket一并推到clients数组中
// socket是双工的 指的是A ——- B之间的连接
// 如果有100个客户端 就会建立100个socket
// 可以用数组存储起来 让每个客户端都能收到彼此的信息
clients.push({ id: clientId.toString(), socket });
});
同时在客户端用户输入的时候要传入Id,改写ask方法,这里的moveCursor和clearLine只是为了让ui更好看,具体可以看node官方文档
const ask = async () => {
const message = await rl.question('Enter a message > ');
// 用户输入完了 我们也得到message了 就移动光标得到Enter a message > 这一行
await moveCursor(0, -1);
await clearLine(0);//再删除这一行
// 在发送信息的时候要告诉服务器是哪个id
socket.write(`${id}-message-${message}`);
};
ask();
const clearLine = (dir) => {
// dir <number>
// -1: to the left from cursor
// 1: to the right from cursor
// 0: the entire line
return new Promise((resolve, reject) => {
process.stdout.clearLine(dir, () => {
resolve();
});
});
};
const moveCursor = (dx, dy) => {
return new Promise((resolve, reject) => {
process.stdout.moveCursor(dx, dy, () => {
resolve(); //这里为什么是process.stdout 然后这一步的作用是
});
});
};
最后,服务端收客户端的输入就要广播
socket.on('data', (data) => {
const dataString = data.toString('utf-8');
const id = dataString.substring(0, dataString.indexOf('-'));
const message = dataString.substring(dataString.indexOf('-message-') + 9);
clients.map((client) => {
client.socket.write(`> User ${id} : ${message}`);
});
});
再加上 有人加入或退出就广播
socket.on('end', () => {
clients.map((client) => {
client.socket.write(`User ${clientId} left!`); //有人断开socket连接 为什么这里要去map呢 //因为要广播,告诉所有的客户端 //怎么找到对应的clientId的?//socket是一对一的
});
});
客户端收到数据的处理
socket.on("data",async(data) => {
// console.log();
// await moveCursor(0,-1);//这个不是多此一举吗
// await clearLine(0);
if(data.toString("utf-8").substring(0,2) ==="id"){
id = data.toString("utf-8").substring(3);//截取到最后一位的话不会把-message-${message}也
console.log(`your id is ${id}`)
}else{
console.log(data.toString("utf-8"))
}
ask()
})
完整代码:
客户端
const net = require('net');
const readline = require('readline/promises'); //提供接口读取readable stream中的内容
const PORT = 3099;
const HOST = '127.0.0.1';
// 用nodejs readline读取命令行界面
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
// process.stdin返回一个双工的流 可读的stream
});
const clearLine = (dir) => {
// dir <number>
// -1: to the left from cursor
// 1: to the right from cursor
// 0: the entire line
return new Promise((resolve, reject) => {
process.stdout.clearLine(dir, () => {
resolve();
});
});
};
const moveCursor = (dx, dy) => {
return new Promise((resolve, reject) => {
process.stdout.moveCursor(dx, dy, () => {
resolve(); //这里为什么是process.stdout 然后这一步的作用是
});
});
};
let id;
//HACK 返回net.Server
// socket是双工的 指的是A ——- B之间的连接. 如果有100个客户端 就会建立100个socket
const socket = net.createConnection({ host: HOST, port: PORT }, async () => {
console.log('connected to the server!');
const ask = async () => {
const message = await rl.question('Enter a message > ');
// 用户输入完了 我们也得到message了 就移动光标得到Enter a message > 这一行
await moveCursor(0, -1);
await clearLine(0);//再删除这一行
// 在发送信息的时候要告诉服务器是哪个id
socket.write(`${id}-message-${message}`);
};
ask();
socket.on("data",async(data) => {
// console.log();
// await moveCursor(0,-1);//这个不是多此一举吗
// await clearLine(0);
if(data.toString("utf-8").substring(0,2) ==="id"){
id = data.toString("utf-8").substring(3);//截取到最后一位的话不会把-message-${message}也
console.log(`your id is ${id}`)
}else{
console.log(data.toString("utf-8"))
}
ask()
})
});
socket.on("end", () => {
console.log("Connection was ended!");
});
服务端:
const net = require('net');
const PORT = 3099;
const HOST = '127.0.0.1';
const server = net.createServer(); //HACK 返回net.Server
// 如果有100个客户端 就会建立100个socket 可以用数组存储起来 让每个客户端都能收到彼此的信息
const clients = [];
server.on('connection', (socket) => {
console.log('A new Connection to the server');
// 谁发送了这个信息?为连接到的每个客户端分配id
const clientId = clients.length + 1;
// 同时广播它的id
clients.map((client) => {
client.socket.write(`User ${clientId} joined`); //这个是在所有的客户端都会收到的:除了刚刚加入的这台客户端它自己不会收到 广播
});
// 告诉客户端被分配到了哪个id
socket.write(`id-${clientId}`); //这个和上面的有什么差别 这个是没有写到client的socket里面的 //这个只会在建立连接的socket收到
socket.on('data', (data) => {
const dataString = data.toString('utf-8');
const id = dataString.substring(0, dataString.indexOf('-'));
const message = dataString.substring(dataString.indexOf('-message-') + 9);
clients.map((client) => {
client.socket.write(`> User ${id} : ${message}`);
});
});
// 有人加入或退出就广播
socket.on('end', () => {
clients.map((client) => {
client.socket.write(`User ${clientId} left!`); //有人断开socket连接 为什么这里要去map呢 //因为要广播,告诉所有的客户端 //怎么找到对应的clientId的?//socket是一对一的
});
});
// 有客户端连接就把他的id和socket一并推到clients数组中
// socket是双工的 指的是A ——- B之间的连接
// 如果有100个客户端 就会建立100个socket
// 可以用数组存储起来 让每个客户端都能收到彼此的信息
clients.push({ id: clientId.toString(), socket });
});
server.listen(PORT, HOST, () => {
console.log('open server on', server.address());
});