日星网 windows 中文论坛

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 303|回复: 0

跟着《Node即学即用》学做聊天服务器

[复制链接]
发表于 2017-3-15 02:00:17 | 显示全部楼层 |阅读模式
首先,我们需要在Node中包含 TCP 模块, 并创建一个新的TCP服务器

  1. // JavaScript Document
  2. var net = require("net"); //创建net  TCP的连接

  3. var chatServer = net.createServer(); //创建服务器

  4. chatServer.on('connection', function(client){
  5.     client.write('Hi!\n');
  6.     client.write('Bye!\n');

  7.     client.end(); //关闭服务
  8. })

  9. chatServer.listen(8081);
复制代码


现在我们可以通过浏览器或是 Telnet 来连接服务器了。
最终结果会显示  Hi! Bye! 然后就断开服务了。

接下来 我们要监听所有由客户端过来的连接请求

  1. // JavaScript Document
  2. var net = require("net"); //创建net  TCP的连接

  3. var chatServer = net.createServer(); //创建服务器

  4. chatServer.on('connection', function(client){
  5.     client.write('Hi!\n');
  6.    
  7.         client.on('data', function(data){  //当client发送数据给服务器的时候会触发此事件
  8.                 console.log(data)
  9.         })

  10. })

  11. chatServer.listen(8081);
复制代码


新监听器关注的是data事件,每当client发送数据给服务器时,这一事件都会被触发,并处理为二进制数据。

客户端之间的通信
  1. var net = require("net"); //创建net  TCP的连接

  2. var chatServer = net.createServer(); //创建服务器
  3. var clientList = [];  //声明一个客户端列表

  4. chatServer.on('connection', function(client){
  5.     client.write('Hi!\n');
  6.         clientList.push(client);
  7.    
  8.         client.on('data', function(data){  //当client发送数据给服务器的时候会触发此事件
  9.                 for(var i=0; i<clientList.length; i++){
  10.                         //把数据发给所有客户端
  11.                         clientList[i].write(data);
  12.                 }
  13.         })
  14.    
  15.     //client.end();
  16. })

  17. chatServer.listen(8081);
复制代码


做完到这里,我们就可以看到客户端之间的通信了, 但我们并没有检查发送者是谁,只是简单的把消息转发给所有的客户端。下面我们要解决这个问题。

我们将要在所有发言人的前面添加一个此客户端的ip及端口号作为发言者的名字。并且屏蔽掉发言者自己屏幕上的自己的发言信息
  1. var net = require("net"); //创建net  TCP的连接

  2. var chatServer = net.createServer(); //创建服务器
  3. var clientList = [];  //声明一个客户端列表

  4. chatServer.on('connection', function(client){
  5.         client.name = client.remoteAddress + ':' + client.remotePort;  //remoteAddress 用户地址, remotePort 用户端口
  6.     client.write('Hi! ' + client.name + '\n');
  7.         clientList.push(client);
  8.    
  9.         client.on('data', function(data){  //当client发送数据给服务器的时候会触发此事件
  10.                 broadcast(data, client);
  11.         })

  12. })

  13. function broadcast(message, client){
  14.         for(var i=0; i<clientList.length; i++){
  15.                 //把数据发给所有客户端, 如果不是自己就发给其他人
  16.                 if(client !== clientList[i]){
  17.                         clientList[i].write(client.name + " say " + message);
  18.                 }
  19.         }
  20. }

  21. chatServer.listen(8081);
复制代码


代码运行起来, 嗯,不错还算完美。
不过当其中一个客户端断开连接,再有人发言的时候,服务器端就会出现一个错误,导致全部下线。下面我们就来解决这个问题。

叫我们的服务器更加健壮,并在服务器端显示日志
  1. chatServer.on('connection', function(client){
  2.         client.name = client.remoteAddress + ':' + client.remotePort;  //remoteAddress 用户地址, remotePort 用户端口
  3.     client.write('Hi ' + client.name + '!\n');
  4.         console.log(client.name + ' joined');
  5.         clientList.push(client);
  6.    
  7.         client.on('data', function(data){  //当client发送数据给服务器的时候会触发此事件
  8.                 broadcast(data, client);
  9.         })
  10.        
  11.         client.on('end', function(){
  12.                 console.log(client.name + ' quit')
  13.                 clientList.aplice(clientList.indexOf(client), 1)
  14.         })

  15.         client.on('error', function(){
  16.                 console.log(e); //显示出错事件
  17.         })
  18. })
复制代码


检查socket的可写状态
  1. function broadcast(message, client){
  2.         var cleanup = [];
  3.         for(var i=0; i<clientList.length; i++){
  4.                 //把数据发给所有客户端, 如果不是自己就发给其他人
  5.                 if(client !== clientList[i]){
  6.                         // 检查socket是否可写,以确保不会因为任何一个不可写的socket导致异常。发现不可写的socket,通过Socket.destroy()方法将其关闭,并移除clientList
  7.                         if(clientList[i].writable){
  8.                                 clientList[i].write(client.name + " say " + message);
  9.                         }else{
  10.                                 cleanup.push(clientList[i]);
  11.                                 clientList[i].destroy();
  12.                         }
  13.                 }
  14.         }
  15.        
  16.         for(i=0; i<cleanup.length; i++){
  17.                 clientList.splice(clientList.indexOf(cleanup[i]), 1);
  18.         }
  19. }
复制代码

您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

手机版|小黑屋|日星网 ( 黑ICP备07001742号 )

GMT, 2018-11-17 03:18 PM , Processed in 0.019360 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表