node模块之net模块——socket

当我们去面试的时候,常常会遇到这样一个问题:当用户在浏览器地址栏输入一段url发出资源请求后,到服务端返回数据呈现给用户的这个过程都发生了什么?

我们把进行通信的这两个端(这里指的是,浏览器和资源获取的地方)称之为客户端和服务端。我们连通两个端进行通信,靠的就是socket这个东西。他将特定格式的内容进行传递,以达到客户端和服务端通信的目的。

最近刚好在学习node的net模块,接触到这一块内容。下面就来看看node中socket通信的一种实现方式。

client.js

// 客户端

const net = require('net');

const readline = require('readline');
const rl = readline.createInterface(process.stdin, process.stdout);

rl.question('What is your name? ', (name) => {
  name = name.trim();
  if (!name) {
    throw new Error('名字没有提供');
  }
  // 创建于服务端的连接
  var server = net.connect({ port: 2080, host: '192.168.1.56' }, () => {

    console.log(`Welcome ${name} to 2080 chatroom`);

    // 监听服务端发过来的数据
    server.on('data', (chunk) => {
      try {
        var signal = JSON.parse(chunk.toString().trim());
        var procotol = signal.procotol;
        switch (procotol) {
          case 'boardcast':
            console.log('\nboardcast[' + signal.from + ']> ' + signal.message + '\n');
            rl.prompt();
            break;
          default:
            server.write('再瞅试试!');
            break;
        }
      } catch (error) {
        server.write('你瞅啥!');
      }
    });

    rl.setPrompt(name + '> '); // 此时没有写到控制台

    rl.prompt(); // 写入控制台

    // 输入一行内容敲回车触发   
    rl.on('line', (line) => {

      // {"procotol":"boardcast","from":"张三","message":"你瞅啥!"}
      var send = {
        procotol: 'boardcast',
        from: name,
        message: line.toString().trim()
      };

      server.write(JSON.stringify(send));

      rl.prompt();

    })
    .on('close', () => {
      // console.log('Have a great day!');
      // process.exit(0);
    });

  });
});

server.js

// 建立一个Socket服务端

const net = require('net');

// 用于存储所有的客户端连接
var clients = [];

var server = net.createServer((socket) => {

  // socket.setEncoding('utf8');

  // 哪个客户端与我连接socket就是谁
  clients.push(socket);

  console.log(`Welcome ${socket.remoteAddress} to 2080 chatroom 当前在线${clients.length}`);

  // 触发多次
  socket
  .on('data', clientData)
  .on('error', (err) => {
    clients.splice(clients.indexOf(socket), 1);
    console.log(`${socket.remoteAddress}下线了 当前在线${clients.length}`);
  });

});

// 广播消息
function boardcast(signal) {
  // console.log(signal);
  // 肯定有用户名和消息
  var username = signal.from;
  var message = signal.message;
  // 我们要发给客户端的东西
  var send = {
    procotol: signal.procotol,
    from: username,
    message: message
  };
  // 广播消息 遍历每一个客户端,并向其写入内容
  clients.forEach(client => {
    client.write(JSON.stringify(send)); 
  });
}

// 有任何客户端发消息都会触发
function clientData(chunk) {
  // chunk:boardcast|张三|你瞅啥!
  // chunk:{"procotol":"boardcast","from":"张三","message":"你瞅啥!"}
  // chunk:{"procotol":"p2p","from":"张三","to":"李四","message":"瞅你咋地!"}
  try {
    var signal = JSON.parse(chunk.toString().trim());
    var procotol = signal.procotol;
    switch (procotol) {
      case 'boardcast':
        boardcast(signal);
        break;
      // case 'p2p':
      //   p2p(signal);
      //   break;
      // case 'shake':
      //   shake(signal);
      //   break;
      default:
        socket.write('再瞅试试!');
        break;
    }
  } catch (error) {
    socket.write('你瞅啥!');
  }
}

var port = 2080;
server.listen(port, (err) => {
  if (err) {
    console.log('端口被占用');
    return false;
  }
  console.log(`服务端正常启动监听【${port}】端口`);
});

 

posted @ 2018-10-11 12:45  一江西流  阅读(2006)  评论(0编辑  收藏  举报