基于NodeJs的局域网聊天室

1.该系统基于nodeJs,electron旨在开发一个桌面端的简单聊天系统(1对1)
2.基于nodeJs的socket编程


思路:
首先需要一个服务器,用来做中转服务,并做一些逻辑判断,从而达到一对一聊天的目的
客户端只需连接服务器,制定一定的数据格式进行发送数据即可
具体的界面则用electron来处理


服务器代码:

var net = require('net'); // 使用net模块(创建TCP的SOCKET)
var PORT = 8080; //端口参数
var server = net.createServer(); //创建一个tcp的服务器
var room = [];//定义一个聊天室的数组

//on函数作用是监听函数,第一个参数为监听的数据名,第二个是监听到后执行的回调函数
server.on('connection', function (socket) {  //监听connect连接,即当客户端发起链接时,服务器捕获该链接,执行后面的函数
//客户端和服务器完成TCP链接后 会生成一个socket,这里作为回调的参数获取
  console.log("new connection" + socket.remoteAddress + ':' + socket.remotePort);
  socket.on('data', function (data) { //给socket 添加监听事件,即当客户端和服务器连接上后 进行的传输皆用该socket 进行
    var data = JSON.parse(data.toString().trim()); //JSON.parse 可将json字符串转换为json对象 【socket传输的时候只支持字符串/二进制】
   //分别获取data内的内容 
    var from = data.from;
    var to = data.to;
    var msg = data.msg;
 //定制聊天室数组内存储的json的格式,用来限制1对1聊天
    var singelRoom = {
      "name1": from,
      "name1S": socket,
      "name2": to
    }
 //如果聊天室为空 直接放入第一个单人聊天室json数据
    if (room.length == 0) {
      room.push(singelRoom);
    }
    var flag = 0;
// 遍历聊天室中的内容
    for (var i in room) {
//聊天室中存的是自己和对方的聊天信息 则执行
      if ((room[i].name1 == from && room[i].name2 == to) || (room[i].name1 == to && room[i].name2 == from)) {
        flag = 1;
    //准确的存入自己的socket
        if(room[i].name1 == from){
          room[i].name1S = socket;
        }
        if(room[i].name2 == from){
          room[i].name2S = socket;
        }
//  如果当前socket 和 单人聊天室json数据的信息一致 则获取第一方的socket
        if (room[i].name1S == socket) {
          if (room[i].name2S != null) {
            var toSocket = room[i].name2S;
            toSocket.write(msg);
          } else {
             //对方socket为空 说明对方没有发送data信息,这里没有保存他的socket信息(可以理解为对方发送消息才算上线,这里就算未上线)
            socket.write("等待对方上线");
          }
        } else {
          room[i].name2S = socket;
          if (room[i].name1S != null) {
            var toSocket = room[i].name1S;         
            toSocket.write(msg);
          } else {
            socket.write("等待对方上线");
          }
        }
      }
    }
    if (flag == 0) {
      //console.log("first");
      room.push(singelRoom);
      //console.log(room.length);
      socket.write("等待对方上线");
    }
  });

//监听客户端的close事件(即下线)
  socket.on('close', function () {
    //从聊天室中找到当前的socket 并把它置为空
    if(socket!=null){
      for (var i in room) {
        if(room[i].name1S==socket){
          room[i].name1S=null;
        }
        else if(room[i].name2S==socket){
          room[i].name2S=null;
        }
        else{
          break;
        }
      }
    }
    console.log('A client closed');
  });

//监听socket错误,并打印
  socket.on('error',(err)=>{ 
    console.log("下线请求!"+err);
  });
});

server.on('error', function (err) {
  console.log('server error:', err.message);
});

server.on('close', function () {
  console.log('server closed');
});
//服务器监听地址 0.0.0.0  端口8080
server.listen(PORT, '0.0.0.0');

客户端:
页面(index.html):[这里用的electron来处理,这里只涉及index.html和相关的js,具体main.js的知识请大家查看electron相关的文档]

 <!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>聊天室</title>
  <link rel="stylesheet" href="./lib/stone.css">
  <style>
    body{
      overflow: hidden;
    }
    h1{
      font-size: 25px;
      font-weight: bold;
    }
    input{
      border:1px solid gray;
    }
    textarea{
      outline: 0;
      height: 128px;
      border-top: 1px solid gray;
      border-bottom: 1px solid gray;
      width: 96%;
      padding: 20px;
      margin: 0 auto;
      resize : none;
    }
    #content {
      display: none;
    }
    #start{
      display: none;
    }
    #welcome{
      width: 100%;
      height: 600px;
      text-align: center;
      color: white;
    }
    #welcome h1{
      padding-top: 200px;
    }
    #welcome h4{
      margin-top: 150px;
      font-size: 14px;
    }
    #welcome h5{
      margin-top: 5px;
      font-size: 12px;
    }
    #start_box{
      width: 400px;
      height: 200px;
      margin: 0 auto;
      text-align: center;
    }
    #start_box h1{
      padding-top: 50px;
      margin-bottom: 100px;
    }
    #start_box p{
      padding-bottom: 11px;
    }
    #start_box input{
      height: 30px;
      text-align: center;
    }
    #sendBtn{
      outline: 0;
      width:110px;
      height: 40px;
      line-height: 40px;
      text-align: center;
    }
    #chatMsg{
      width: 90%;
      margin: 0 auto;
      padding: 20px;
      height: 290px;
      overflow: auto;
    }
    #sendMsg{
      float: right;
      position: relative;
      right: 10px;
      width: 80px;
      height: 30px;
      line-height: 30px;
      border: 1px solid grey;
    }
    From,To{
      width:100%;
      font-size: 12px;
      margin-bottom: 5px;
    }
    .title{
      font-weight: bold;
      font-size: 16px;
    }
  </style>
</head>
<body>
  <div id="welcome" class="lightBlue">
    <h1>局 域 网 聊 天 室</h1>
    <h4>正在进入...</h4>
    <h5>by 袁浩宇/李雪可(echoun)</h5>    
  </div>
  <div id="start">
    <div id="start_box">
      <h1 class="tc">欢迎使用聊天室软件</h1>
      <p>请输入当前用户号码:</p><input type="text" id="from"><br/><br/>
      <p>请输入对方用户号码:</p><input type="text" id="to"><br/><br/>
      <button id="sendBtn" class="Sbs">开始聊天</button>
    </div>
  </div>
  <div id="content">
    <div id="chatMsg"></div>
    <div id="txt">
      <textarea name="" id="msg"></textarea><br/>
      <button id="sendMsg" onclick="sendMsg()">发送</button>
    </div>
  </div>
</body>
<script>
  // You can also require other files to run in this process
  require('./client.js')
</script>
</html>

逻辑:(client.js)

 var net = require('net');
 var PORT = 8080;
 var From, To;
 var Msg = null;

//显示逻辑(4s后welcome的div 隐藏 start的div 显示)
 setTimeout(function () {
   document.getElementById("welcome").style.display = "none";
   document.getElementById("start").style.display = "block";
 }, 4000)
 
//创建客户端(需要制定port,即服务器监听的port 还有就是host参数,这里我没有写 默认为127.0.0.1 如果要局域网通信则写服务器的地址,其他的默认值具体可以去看官方文档)
 var client = net.connect({port: PORT}, function () {
   document.getElementById('sendBtn').onclick = function () {
    //获取from 和 to 的值
     From = document.getElementById("from").value;
     To = document.getElementById("to").value;
     if (From == To && From != "") {
       alert("请输入不一样的号码!");
       return 0;
     }
     if (From == "" || To == "") {
       alert("输入不能为空");
       return 0;
     }
     document.title = From + '正在与' + To + '通话';
     document.getElementById("start").style.display = "none";
     document.getElementById("content").style.display = "block";
   }
   document.getElementById('sendMsg').onclick = function () {
     var myDate = new Date();
     Msg = document.getElementById("msg").value;
     if(Msg==""){
       alert("输入空值给你的小伙伴看,并没有什么意义哦!");
       return 0;
     }
   //定义要发送数据的格式
     var send = {
       from: From,
       to: To,
       msg: Msg
     };
     client.on('error', function (err) {
       alert('请检查服务器是否正确启动!');
       console.log(err);
     });
   //将自己发出的数据 显示在页面中
     var textNodeTo = document.createElement('div');
     textNodeTo.innerHTML = '<p class="title">' + From + ' - 【Time ' + myDate.getHours() + ':' + myDate.getMinutes() + ':' + myDate.getSeconds() + '】</p>' + '<p>' + Msg.toString() + '</p>';
     textNodeTo.className = 'To tr tblue';
     var parentNode = document.getElementById("chatMsg");
     parentNode.appendChild(textNodeTo);
  // socket的写操作,注意传输时转换成字符型
     client.write(JSON.stringify(send));
     document.getElementById("msg").value = null;
   };

 });

//监听data,及获取服务器发来的信息
 client.on('data', function (data) {
// 显示在页面上
   var myDate = new Date();
   var textNodeFrom = document.createElement('div');
   textNodeFrom.innerHTML = '<p class="title">' + To + ' - 【Time ' + myDate.getHours() + ':' + myDate.getMinutes() + ':' + myDate.getSeconds() + '】</p>' + '<p>' + data.toString() + '</p>';
   textNodeFrom.className = 'From tl tgreen';
   var parentNode = document.getElementById("chatMsg");
   parentNode.appendChild(textNodeFrom);
 });

 client.on('end', function () {
   console.log('Disconnected from server');
   process.exit();
 });

总体来说这里还是讲的比较啰嗦啦,如果想直接使用,可以通过下面的传送门。

传送门:https://github.com/yuanhaoyu/Chatroom (觉得不错可以star 支持一哈)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 开始教程之前,请允许我假设你已经有了一个常用的的编辑器(或者 IDE),系统中也安装了Node.js 和 npm,...
    程序人生_小龙阅读 49,785评论 1 38
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • 这个暑期我过的超有意义了,现在先让你们看看我做的小手工吧! 暑期我经常跟姐姐去体育馆踢足球,运动。妈妈说要坚持锻炼...
    Alice昔日猪猪阅读 295评论 0 0
  • 六、一班 刘羽轩 人的生命是非常短暂的,我们出生到去世的过程就叫做一生。当然,在这一生里我们可以忙忙碌碌无为,也...
    一花匠阅读 390评论 0 0
  • 我的同学,大学同学,城里人,麦子和韭菜是分不清的。我们经常和她开玩笑。有次上课,她又打破了我们的认知。 讲课的时候...
    开心的灵通阅读 766评论 0 0