1. 程式人生 > >基於NodeJs的區域網聊天室

基於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");
   console.log(textNodeFrom);
   parentNode.appendChild(textNodeFrom);
   console.log(data.toString());
 });

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