node.js入门 - 2.创建一个简单聊天室

简介:   这篇文章将通过开发一个简单聊天室的方式,介绍node.js的net模块。      一、第一版,只向客户端发送信息     我们先实现一个简单的版本,代码如下: var net=require('net'); var chatServer=net.

  这篇文章将通过开发一个简单聊天室的方式,介绍node.js的net模块。

  

  一、第一版,只向客户端发送信息

 

  我们先实现一个简单的版本,代码如下:

var net=require('net');
var chatServer=net.createServer();
chatServer.on('connection',function(client){
    client.write('hi!\n');
    client.write('bye!\n');
    client.end();
})
chatServer.listen(9001);

  代码讲解:  

1.因为我们要使用tcp作为通信协议,node中tcp相关的类是放在net模块中的,所以我需要先引用net。

2.通过net.createServer()就为我们创建了一个tcp的服务器。

3.接下来使用on方法实现对connection事件的监听。每当有一个新的客户端连接到我们的tcp服务器的时候,都会触发connection对应的方法,向客户端输出‘hi!bye!’的文字    信息。然后通过client.end()关闭连接。

4.程序最后通过chatServer.listen(9001);实现对9001端口的监听。

 

  运行服务器:

  使用webstorm的调试工具运行我们的服务器。

  

  运行客户端:

  打开window的命令行工具,

输入如下命令:

telnet 127.0.0.1 9001

回车,输出如下结果:

 

  note:

  自己实践上面例子的时候遇到了点小状况,我最开始使用的是9000端口,运行的时候程序要报错。

events.js:66
        throw arguments[1]; // Unhandled 'error' event
                       ^
Error: listen EADDRINUSE
    at errnoException (net.js:769:11)
    at Server._listen2 (net.js:909:14)
    at listen (net.js:936:10)
    at Server.listen (net.js:985:5)
    at Object.<anonymous> (D:\workspace\nodejs\chatroom\chatServer.js:8:12)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)

  ‘EADDRINUSE’这个东西让人很费解,完全不知道是什么意思,借助有道的翻译,意思是:错误地址使用。‘EADDRINUSE’应该是‘error address in use’的缩写。后来借助google找到了合理的解释,说是你监听的端口已经被使用了,我把端口换成了9001,一切正常。

  当遇到异常的时候,不知道node有没有提供帮助的地方,光靠他提供的异常信息提示真是解决不了问题啊。或许最好的帮手就是google。

 

  二、第二版,可以接收客户端信息:

  代码如下:

var net=require('net');
var chatServer=net.createServer();
var clientList=[];

chatServer.on('connection',function(client){
    client.write('hi!\n');
    clientList.push(client);
    client.on('data',function(data){
        for(var i= 0,len=clientList.length;i<len;i++){
            if(client!=clientList[i]){
                clientList[i].write(data);
            }
        }
        console.log(data);
    });
})
chatServer.listen(9001);

  这版比第一版有两个变化点,一是增加了client的on方法,二是移出了client.end();方法。client的on方法添加data事件,这样客户端每次发送数据,服务器都可以接收到。移出client.end()是因为,如果我们关闭了链接,客户端再发送新数据,服务器就无法接收了。

  我们来看运行结果,其中‘hello’是客户端输入信息,红线框住的是服务器端接收到的信息,注意它是二进制数据,需要我们做相应的处理才能转换成字符串,后面的课程会有介绍。

 

  三、第三版,实现客户端和服务器端的相互通信:

  在这里我们需要把每个客户端都放到一个数组变量里面缓存起来,遍历数组,使用client.write()方法对每个客户端做出反应。我们来看代码:

var net=require('net');
var chatServer=net.createServer();
var clientList=[];

chatServer.on('connection',function(client){
    client.write('hi!\n');
    clientList.push(client);
    client.on('data',function(data){
        for(var i= 0,len=clientList.length;i<len;i++){
            if(client!=clientList[i]){
                clientList[i].write(data);
            }
        }
        console.log(data);
    });
})
chatServer.listen(9001);

  我们创建了clientList来存放客户端连接,每当有新连接进来的时候,把client对象保存入数组。接下来,判断遍历到的client是否是当前client,不是的话输出data。

  

  note:

  这里大家注意‘len=clientList.length’部分,我们把clientList.length存入变量len,这样可以提高程序的性能。在 i<len 运算的时候,就不用每次再去取clientList.length了,大家可以在自己的程序里也使用这样的方式,特别是数组比较大的时候。

  

  我们来看运行结果,要打开多个telnet链接,红色为输入信息,蓝色为输出信息:

  四、最终版

  我们增加了客户断开链接的 end 事件,在end事件和发送消息的过程中会清理不存在的客户端。

var net=require('net');
var chatServer=net.createServer();
var clientList=[];

chatServer.on('connection',function(client){
    client.name=client.remoteAddress+':'+client.remotePort;
    broadcast('hi,'+ client.name +' join!\r\n',client);
    client.write('hi,'+ client.name +'!\r\n');
    clientList.push(client);

    client.on('data',function(data){
        broadcast(client.name+' say:'+ data+'\r\n',client);
    });

    client.on('end',function(){
        broadcast('hi,'+ client.name +' quit!\r\n',client);
        clientList.splice(clientList.indexOf(client),1);
    });
})

function broadcast(message, client) {
    var cleanup=[];
    for(var i= 0,len=clientList.length;i<len;i++){
        if(client!==clientList[i]){
            if(clientList[i].writable){
                clientList[i].write(message);
            }else{
                cleanup.push(clientList[i]);
                clientList[i].destroy();
            }
        }
    }

    for(var i= 0,len=cleanup.length;i<len;i++){
        clientList.splice(clientList.indexOf(cleanup[i]),1);
    }
}

chatServer.listen(9001);

  运行效果:

三个客户链接到服务器,其中一个向另外两个说‘hello’。

其中一个客户关闭链接:

 

  今天的例子到此为止。

目录
相关文章
|
2月前
|
前端开发 机器人 API
前端大模型入门(一):用 js+langchain 构建基于 LLM 的应用
本文介绍了大语言模型(LLM)的HTTP API流式调用机制及其在前端的实现方法。通过流式调用,服务器可以逐步发送生成的文本内容,前端则实时处理并展示这些数据块,从而提升用户体验和实时性。文章详细讲解了如何使用`fetch`发起流式请求、处理响应流数据、逐步更新界面、处理中断和错误,以及优化用户交互。流式调用特别适用于聊天机器人、搜索建议等应用场景,能够显著减少用户的等待时间,增强交互性。
387 2
|
26天前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
|
26天前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
30 0
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
|
1月前
|
监控 前端开发 JavaScript
React 静态网站生成工具 Next.js 入门指南
【10月更文挑战第20天】Next.js 是一个基于 React 的服务器端渲染框架,由 Vercel 开发。本文从基础概念出发,逐步探讨 Next.js 的常见问题、易错点及解决方法,并通过具体代码示例进行说明,帮助开发者快速构建高性能的 Web 应用。
74 10
|
1月前
|
数据采集 存储 JavaScript
如何使用Puppeteer和Node.js爬取大学招生数据:入门指南
本文介绍了如何使用Puppeteer和Node.js爬取大学招生数据,并通过代理IP提升爬取的稳定性和效率。Puppeteer作为一个强大的Node.js库,能够模拟真实浏览器访问,支持JavaScript渲染,适合复杂的爬取任务。文章详细讲解了安装Puppeteer、配置代理IP、实现爬虫代码的步骤,并提供了代码示例。此外,还给出了注意事项和优化建议,帮助读者高效地抓取和分析招生数据。
如何使用Puppeteer和Node.js爬取大学招生数据:入门指南
|
3月前
|
JavaScript 前端开发 小程序
一小时入门Vue.js前端开发
本文是作者关于Vue.js前端开发的快速入门教程,包括结果展示、参考链接、注意事项以及常见问题的解决方法。文章提供了Vue.js的基础使用介绍,如何安装和使用cnpm,以及如何解决命令行中遇到的一些常见问题。
一小时入门Vue.js前端开发
|
2月前
|
存储 JavaScript 前端开发
前端开发:Vue.js入门与实战
【10月更文挑战第9天】前端开发:Vue.js入门与实战
|
2月前
|
自然语言处理 JavaScript 前端开发
JavaScript高级——ES6基础入门
JavaScript高级——ES6基础入门
27 1
|
2月前
|
机器学习/深度学习 自然语言处理 前端开发
前端大模型入门:Transformer.js 和 Xenova-引领浏览器端的机器学习变革
除了调用API接口使用Transformer技术,你是否想过在浏览器中运行大模型?Xenova团队推出的Transformer.js,基于JavaScript,让开发者能在浏览器中本地加载和执行预训练模型,无需依赖服务器。该库利用WebAssembly和WebGPU技术,大幅提升性能,尤其适合隐私保护、离线应用和低延迟交互场景。无论是NLP任务还是实时文本生成,Transformer.js都提供了强大支持,成为构建浏览器AI应用的核心工具。
522 1
|
2月前
|
Web App开发 JSON JavaScript
深入浅出:Node.js后端开发入门与实践
【10月更文挑战第4天】在这个数字信息爆炸的时代,了解如何构建一个高效、稳定的后端系统对于开发者来说至关重要。本文将引导你步入Node.js的世界,通过浅显易懂的语言和逐步深入的内容组织,让你不仅理解Node.js的基本概念,还能掌握如何使用它来构建一个简单的后端服务。从安装Node.js到实现一个“Hello World”程序,再到处理HTTP请求,文章将带你一步步走进Node.js的大门。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往后端开发新世界的大门。