みてさわって動かして(自作チャット)

AWS Ec2で自作のチャット

いろいろな情報を元にNode.js +Socket.io+ bootstrap で構築してみました。結構前に試してはいたのですが、アウトプットとして発信できていなかったので再度行いました。

 

最終的な成果は、以下で確認して下さい。めっちゃ簡単で、機能不足もありますが、チャットです。

 

ログインボタンを押して初めて下さい。(ブラウザがsafariだとダメでした。。。)

 

ここをクリック(中止してます) yos-chat

 

複数ブラウザか複数タブでアクセスすると、通信が双方向に走るのがわかります。
片方でのメッセージを送ると、それが送られるとか、あとは現在チャットに接続している人数も出ます。ちょこちょこっといじってみて下さい。動作してなかったら、予期せぬエラーなので、コメント欄に書いて下さい・・)

 

今後もどこかで随時機能追加できたらなーと思ってます。 今回やったことをまとめると以下になります。

  • 環境構築
    • Node.jsのinstall
  • 機能追加とデザイン調整しながら試行錯誤
    • サーバーサイドのJSの作成
    • クライアント側のIndex.htmlの作成
    • クライアント側のCSSの作成
    • デザイン調整
  • AWSサーバーで動かす
    • サーバーへのNode.jsのインストール
    • サーバーへのデプロイ
    • 動作検証
  • ブログ記事更新
    • 参考にしたリンクの整理と文章化

 

機能追加とデザイン調整 実際のソース

 

サーバーサイドのJS

var path = require('path');
var express = require('express');
var app = express();
// 1.モジュールオブジェクトの初期化
var fs = require("fs");
var http = require("http").Server(app);
app.use(express.static(path.join(__dirname, 'htdocs')));
http.listen(8000);
var io = require("socket.io").listen(http);
console.log("start to server");
// ユーザ管理ハッシュ
var userHash = new Map();
var counter  = 0;
// 2.イベントの定義
io.sockets.on("connection", function (socket) {
  // 接続開始カスタムイベント(接続元ユーザを保存し、他ユーザへ通知)
  socket.on("connected", function (data) {
    var msg = data.name + " has joined chat ";
    userHash.set(socket.id, data.name);
    counter++;
    //console.log(socket.id);
    //console.log(userHash.get(socket.id));
    io.sockets.emit("countChange",{count:counter});
    io.sockets.emit("publish", {isSystemReply: true,msg: msg});
  });
  // メッセージ送信カスタムイベント
  socket.on("publish", function (data) {
    io.sockets.emit("publish", {msg:data.msg,name:data.name});
  });
  // 接続終了組み込みイベント(接続元ユーザを削除し、他ユーザへ通知)
  socket.on("disconnect", function () {
    if (userHash.get(socket.id)) {
      var name = userHash.get(socket.id);
      var msg = name + " has left";
      userHash.delete(socket.id);
      counter--;
      io.sockets.emit("countChange",{count:counter});
      io.sockets.emit("publish", {isSystemReply:true,msg: msg});
      console.log(msg);
    }
  });
});

 

クライアント側のIndex.html

<!DOCTYPE html>
<html lang="en">
<script src="/lib/jquery.min.js"></script>
<script src="/lib/jquery-ui-1.12.1/jquery-ui.js"></script>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>YOS-CHAT</title>
</head>
<body>
<div class="container-fluid">
  <h1>YOS-CHAT <small>Even small just do it</small></h1>
  <div id="timer"></div>
  <div id="current-member-num">
  <h4>Members in the chat  <small id ="NoM">--</small></h4>
  </div>
  <div id="status"></div>
  <form class="form-inline">
    <div class="form-group">
      <button class= "btn" type="button" value="LogIn" id="ConnectButton"/>
    </div>
    <div class="form-group">
      <input type="text" class="form-control" id="msg_input" style ="width: 30em" placeholder="write your message">
    </div>
    <div class="form-group">
      <button class= "btn" type="button" value="Send"id="sendMessage" onclick="publishMessage();">Send</>
    </div>
  </form>
  <div id="msg" style = "padding: 1em;"></div>
  <div id="dialog" title="Input your name">
    <h3 class="validateTips">Please input your name</h3>
    <label for="name">Name </label>
    <input type="text" name="name" id="dialog-username" value="" class="form-control ui-widget-content ui-corner-all">
  </div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="/chat.js"></script>
<script src="/lib/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
<link rel="stylesheet" type="text/css" href="/chat.css">
<link rel="stylesheet" type="text/css" href="/lib/jquery-ui-1.12.1/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="/lib/bootstrap-3.3.7-dist/css/bootstrap.css">
</body>
</html>

クライアント側のJS/CSSの作成

//定数
var socketio;
var myName;
var msgArea = $("#msg");
var input = $("#msg_input");
var sendButton = $("#sendMessage");
var connectButton = $("#ConnectButton");
var textInput = $("#msg_input");
var number = $("#NoM");
var dialog = $("#dialog");
var userName = $("#dialog-username");
var requiredFields = $().add(userName);
var tips = $(".validateTips");
/*ボタンを押した時の動作*/
//talk
function publishMessage() {
  socketio.emit("publish", {msg: textInput.val(),name:myName});
  textInput.val("");
}
//ユーサー名入力画面を開く
function openDialog(){
  dialog.dialog("open");
}
//login通信の開始
function login(inputUserName){
  myName = inputUserName;
  var data = {name:myName,msg:"You are entered room as " + myName}
  socketio = io.connect('http://yos-blog.com:8000');
  socketio.on("connected", function(name) {
    //do nothing
  });
  socketio.on("publish", function(data) {
    addMessage(data);
  });
  socketio.on("disconnect", function() {
    //do nothing
  });
  socketio.on("countChange",function(data){
    changeCounter(data);
  });
  socketio.emit("connected", data);
  addMessage(data);
  changeComponent(true);
  textInput.focus();
}
//logout通信の終了
function logout(){
  var data = {name:myName,msg:"left this chatting"}
  socketio.emit("disconnect",{});
  socketio.disconnect();
  addMessage(data);
  changeComponent(false);
}
/*メソッド群*/
//メッセージの追加
function addMessage (data) {
  var msg;
  //Login or LogOut
  if(data.isSystemReply){
    msg = new Date().toLocaleTimeString() + ' ' + data.msg;
  }else{
    msg = new Date().toLocaleTimeString() + ' ' + "[" + data.name + "]" + ' ' + data.msg;
  }
  msgArea.prepend(`<div>${msg}</div>`);
}
//コンポーネントの切り替え
function changeComponent(isConnected){
  connectButton.off("click");
  if(isConnected){
      connectButton.on("click",logout);
      connectButton.text("LogOut");
  }else{
      connectButton.on("click",openDialog);
      connectButton.text("LogIn");
      textInput.val("");
      number.text("--")
  }
  input.prop('disabled', !isConnected);
  sendButton.prop('disabled', !isConnected);
}
function changeCounter(data){
  number.text(data.count);
}
function initComponent(){
  initDialog();
  changeComponent(false);
}
function initDialog(){
  dialog.dialog({
    autoOpen: false,
    height: 220,
    width: 375,
    modal: true,
    position: {
        of : connectButton,
        at: 'center bottom',
        my: 'left top'},
    buttons: {
      "Join chatting": pressJoinChat,
      Cancel: function() {
        dialog.dialog("close");
      }
    },
    close: function() {
      dialog.dialog("close");
    }
  });
  function pressJoinChat(){
    if(checkRequiredFields()){
      //temp
      tips.text("please input your name").addClass( "ui-state-highlight" );
            setTimeout(function() {
              tips.removeClass( "ui-state-highlight", 2000 );
            }, 1000 );
      return false;
    }
    dialog.dialog("close");
    login(userName.val());
  }
  function checkRequiredFields(){
    // temp
    requiredFields.removeClass("ui-state-error");
    return userName.val() === "";
  }
  dialog.keypress(function(e) {
      if (e.keyCode == $.ui.keyCode.ENTER) {
        pressJoinChat();
        return false;
      }
  });}
//key bind
$(window).keypress(function(e){
  if (e.keyCode == $.ui.keyCode.ENTER) {
    publishMessage();
    return false;
  }
});
initComponent();

 

AWSで動かす

今回はすでにブログのサイトがあったので、そこにつけくわえる形で対応しています。

参考にしたサイト群

メインで参考にした記事

参考Socket.ioで双方向通信チャットアプリを構築 〜 JSおくのほそ道 #005
 

Node.js のexpress というMVCフレームワークに気付いた時に参考にしたサイト

参考Node.jsのMVCフレームワーク「Express」の基礎知識
参考Node.js、Express.js入門
参考ExpressとSocket.IOを使ったカウンターのサンプル
 

途中で自分をモチベートした記事

参考ブログを三ヶ月毎日続けるためにやったこと
 

サーバーへのNode.jsのインストール

参考Amazon Linuxに Node.js と npm を入れる
 

サーバーへのデプロイ

FileZillaを使ってやりました。まぁ、転送するだけですが。
アクセス権とかでファイルの転送ができなかったら、ここを参考に修正

参考チュートリアル: Amazon Linux への LAMP ウェブサーバーのインストール
 

突然だけど、心に響いた言葉

行動を伴わない想像は何の意味もない Imagination means nothing without doing. by Charlie Chaplin(チャーリー・チャップリン)

 

そう、アウトプットが大事、それでは、また。
0 Shares

3 opinions on “みてさわって動かして(自作チャット)”

  1. コメント、嬉しいでしょ。それがわかってるからコメントしちゃう。
    やるやるとは思っていたけど、まぢ天才だわ兄貴。
    引き続き購読してるからね(^ ^)

コメントを残す

メールアドレスが公開されることはありません。