node.js学习(简单聊天室)

简介: node.js学习(简单聊天室)

在掘金查看该文章

1. TCP服务搭建

1.1 socket

先来粗略了解下socket

套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。 (摘自百度百科)

socket用于在两个基于TCP/IP协议的应用程序之间相互通信.最早出现在UNIX系统中,是UNIX系统主要的信息传递方式.在windows系统中,socket称为winsock.

两种形式的socket:流式套接字,对应与TCP协议.
数据报套接字,对应与UDP协议.

2.创建TCP服务端

server.js(服务端)

const net = require("net");
const sever = net.createServer();
// const clients = [];
const users = [];
const types = require("./types");
sever.on("connection", clientSocket => {
   
   
  console.log("有连接进来,请注意```");
  // clients.push(clientSocket)
  clientSocket.on("data", data => {
    console.log("监听data事件,有人说:", data.toString());
    data = JSON.parse(data.toString().trim());
    switch (data.type) {
      case types.login:
        if (users.find(item => item.nickName === data.nickName)) {
          return clientSocket.write(
            JSON.stringify({
              type: types.login,
              success: false,
              message: "昵称已存在"
            })
          );
        }
        clientSocket.nickName = data.nickName;
        users.push(clientSocket);
        clientSocket.write(
          JSON.stringify({
            type: types.login,
            success: true,
            message: "登录成功",
            nickName:data.nickName,
            sumUsers: users.length
          })
        );
        users.forEach(user=>{
          if(user!==clientSocket){
            user.write(JSON.stringify({
              type:types.log,
              message:`${
   
   data,nickName} 进入聊天室,当前在线用户数${
   
   user.length}`
            }))
          }
        })


        break;
      // 群聊天
      case types.broadcast:
         users.forEach(item => {
          item.write(JSON.stringify({
            type:types.broadcast,
            message:data.message,
            nickName:clientSocket.nickName
          }))
        })
        break;
      // 点对点
      case types.p2p:
        const user = users.find(item => item.nickName === data.nickName)
        if(!user){
          return clientSocket.write(JSON.stringify({
            type:types.p2p,
            success:false,
            message:"该用户不存在"
          }))
        }
        console.log('clientSocket.nickName',clientSocket.nickName)
        user.write(JSON.stringify({
          type:types.p2p,
          message:data.message,
          nickName:clientSocket.nickName,
          success:true
        }))

        break;
      default:
        break;
    }
  });

  // 离线
  clientSocket.on("end",()=>{
    console.log("有用户离线了~~~")
    const index =users.findIndex(user => user.nickName === clientSocket.nickName)
    if(index !== -1){
      const offlineUser = users[inde]
      users.splice(index,1)
      users.forEach(user=>{
        if(user!==clientSocket){
          user.write(JSON.stringify({
            type:types.log,
            message:`${
   
   offlineUser,nickName} 离开了聊天室,当前在线用户数${
   
   user.length}`
          }))
        }
      })
    }
  })
  // clientSocket.write('hello,返回的是buffer,用tostring转一下哦')
});

sever.listen(2000, () => {
   
   
  console.log("server running  127.0.0.1 2000");
});

3.创建客户端

client.js(客户端)

const net = require("net");
const types = require("./types");
let nickName = null;
const client = net.createConnection({
   
   
  host: "127.0.0.1",
  port: 2000
});

client.on("connect", () => {
   
   
  console.log("连接成功了~~~");
  process.stdout.write("请输入昵称:");

  // 连接完毕后,可以监听终端的信息,发给服务端
  process.stdin.on("data", data => {
   
   
    data = data.toString().trim();
    console.log("nickName", nickName);
    if (!nickName) {
   
   
      client.write(
        JSON.stringify({
   
   
          type: types.login,
          nickName: data
        })
      );
    }
    const matches = /^@(\w+)\s(.+)$/.exec(data);
    if (matches) {
   
   
      //符合 @xxx xxx  格式
      return client.write(
        JSON.stringify({
   
   
          type: types.p2p,
          nickName: matches[1],
          message: matches[2]
        })
      );
    }
    //群聊天
    client.write(
      JSON.stringify({
   
   
        type: types.broadcast,
        message: data
      })
    );
  });
});

client.on("data", data => {
   
   
  // console.log("服务端发来的data:::", data.toString());
  data = JSON.parse(data.toString().trim());
  switch (data.type) {
   
   
    case types.login:
      if (!data.success) {
   
   
        console.log("登录失败", `${
     
     data.message}`);
        process.stdout.write("请输入昵称");
      } else {
   
   
        process.stdout.write("登录成功,当前在线人数:", data.sumUsers);
        nickName = data.nickName;
      }
      break;
    case types.broadcast:
      console.log(`${
     
     data.nickName}:${
     
     data.message}`);
      break;
    case types.p2p:
      if (!data.success) {
   
   
        return console.log(`发送失败:${
     
     data.message}`);
      }
      console.log(`${
     
     data.nickName}对你说:${
     
     data.message}`);
      break;
    case types.log:
      console.log(`${
     
     data.message}`);
      break;
    default:
      console.log("未知消息类型哦~");
      break;
  }
});

types.js

module.exports = {
  login: 0,
  broadcast: 1,
  p2p: 2,
  log: 3
};

总结

  • 通过net模块建立TCP服务
  • TCP必须建立连接(3次握手)后才能通信
  • socket通信模型
  • 和使用其他node模块(如koa)一样的思路,都是先建立服务(server),指定端口号
相关文章
|
29天前
|
Web App开发 JavaScript 前端开发
如何学习JavaScript?
如何学习JavaScript?
38 5
|
2月前
|
JavaScript 前端开发 开发者
VUE 开发——Node.js学习(一)
VUE 开发——Node.js学习(一)
84 3
|
28天前
|
JavaScript 前端开发 索引
JavaScript学习第二章--字符串
本文介绍了JavaScript中的字符串处理,包括普通字符串和模板字符串的使用方法及常见字符串操作方法如`charAt`、`concat`、`endsWith`等,适合前端学习者参考。作者是一位热爱前端技术的大一学生,专注于分享实用的编程技巧。
23 2
|
28天前
|
存储 JavaScript 前端开发
JavaScript学习第一章
本文档介绍了JavaScript的基础知识,包括其在网页中的作用、如何通过JavaScript动态设置HTML元素的CSS属性,以及JavaScript中的变量类型(`var`、`let`、`const`)和数据类型(基本数据类型与引用数据类型)。通过实例代码详细解释了JavaScript的核心概念,适合初学者入门学习。
48 1
|
2月前
|
JavaScript
js学习--制作猜数字
js学习--制作猜数字
42 4
js学习--制作猜数字
|
2月前
|
JavaScript
webpack学习五:webpack的配置文件webpack.config.js分离,分离成开发环境配置文件和生产环境配置文件
这篇文章介绍了如何将webpack的配置文件分离成开发环境和生产环境的配置文件,以提高打包效率。
52 1
webpack学习五:webpack的配置文件webpack.config.js分离,分离成开发环境配置文件和生产环境配置文件
|
3月前
|
算法 JavaScript 前端开发
第一个算法项目 | JS实现并查集迷宫算法Demo学习
本文是关于使用JavaScript实现并查集迷宫算法的中国象棋demo的学习记录,包括项目运行方法、知识点梳理、代码赏析以及相关CSS样式表文件的介绍。
第一个算法项目 | JS实现并查集迷宫算法Demo学习
|
3月前
|
JavaScript 前端开发 API
紧跟月影大佬的步伐,一起来学习如何写好JS(上)
该文章跟随月影老师的指导,探讨了编写优质JavaScript代码的三大原则:各司其职、组件封装与过程抽象,通过具体示例讲解了如何在实际开发中应用这些原则以提高代码质量和可维护性。
紧跟月影大佬的步伐,一起来学习如何写好JS(上)
|
2月前
|
JavaScript
js学习--制作选项卡
js学习--制作选项卡
38 4
|
3月前
|
移动开发 前端开发 HTML5
Twaver-HTML5基础学习(8)拓扑元素(Element)_网元(Element)、节点(Node)
本文介绍了Twaver HTML5中的拓扑元素(Element),包括网元(Element)、节点(Node)和连线(Link)的基本概念和使用方法。文章详细解释了Element的属性和方法,并通过示例代码展示了如何在React组件中创建节点、设置节点属性和样式。
57 1
Twaver-HTML5基础学习(8)拓扑元素(Element)_网元(Element)、节点(Node)