-- server.js
// ********* server.js 파일
// 전역 변수
const colors = ["red", "green", "blue", "magenta", "purple", "plum", "orange"];
const clients = [];
let history = [];
// HTTP 서버(express) 생성 및 구동
// 1. express 객체 생성
const express = require("express");
const app = express();
// 2. "/" 경로 라우팅 처리
app.use("/", (req, res) => {
res.sendFile(__dirname + "/chat.php");
}); // index.html 파일 응답
// 3. 8080 port에서 서버 구동
const HTTPServer = app.listen(8080, () => {
console.log("Server is open at port:8080");
});
const wsModule = require("ws");
// 2. WebSocket 서버 생성/구동
const wsServer = new wsModule.Server({
server: HTTPServer,
// port: 8081,
// WebSocket서버에 연결할 HTTP서버를 지정한다.
// port: 30002 // WebSocket연결에 사용할 port를 지정한다(생략시, http서버와 동일한 port 공유 사용)
});
// connection(클라이언트 연결) 이벤트 처리
wsServer.on("connection", (ws, request) => {
const index = clients.push(ws) - 1;
let userName = false;
let userColor = false;
// 1) 연결 클라이언트 IP 취득
const ip =
request.headers["x-forwarded-for"] || request.connection.remoteAddress;
console.log(`새로운 클라이언트[${ip}] 접속`);
// 2) 클라이언트에게 메시지 전송
if (ws.readyState === ws.OPEN) {
// 연결 여부 체크
ws.send(`클라이언트[${ip}] 접속을 환영합니다 from 서버`); // 데이터 전송
}
// 3) 클라이언트로부터 메시지 수신 이벤트 처리
ws.on("message", (msg) => {
if (userName === false) {
userName = htmlEntities(msg);
userColor = colors.shift();
ws.send(makeResponse("color", userColor));
console.log(`User is known as: ${userName} with ${userColor} color`);
} else {
console.log(`Received Message from ${userName}: ${msg}`);
const obj = {
time: new Date().getTime(),
text: htmlEntities(msg),
author: userName,
color: userColor,
};
history.push(obj);
history = history.slice(-100);
clients.forEach((client) => client.send(makeResponse("message", obj)));
// ws.send(makeResponse("message", obj));
}
console.log(`클라이언트[${ip}]에게 수신한 메시지 : ${msg}`);
});
// 4) 에러 처리
ws.on("error", (error) => {
console.log(`클라이언트[${ip}] 연결 에러발생 : ${error}`);
});
// 5) 연결 종료 이벤트 처리
ws.on("close", () => {
console.log(`클라이언트[${ip}] 웹소켓 연결 종료`);
if (userName !== false && userColor !== false) {
console.log(`Peer ${ws.remoteAddress} disconnected`);
clients.splice(index, 1);
colors.push(userColor);
}
});
});
// utility
const htmlEntities = (str) =>
String(str)
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """);
const makeResponse = (type, data) => JSON.stringify({ type, data });
- server.js 코딩 후
터미널에서 node server.js 로 웹서버 켜주기
-- client.js
$(function () {
"use strict";
var content = $("#content");
var input = $("#input");
var status = $("#status");
var myColor = false;
var myName = false;
window.WebSocket = window.WebSocket || window.MozWebSocket;
if (!window.WebSocket) {
content.html(
$("<p>", { text: "Sorry, but your browser doesn't support WebSocket." })
);
input.hide();
$("span").hide();
return;
}
var connection = new WebSocket("ws://127.0.0.1:8080");
connection.onopen = function () {
input.removeAttr("disabled");
status.text("이름 입력:");
};
connection.onerror = function (error) {
content.html(
$("<p>", {
text:
"Sorry, but there's some problem with your " +
"connection or the server is down.",
})
);
};
connection.onmessage = function (message) {
try {
console.log(message);
var json = JSON.parse(message.data);
} catch (e) {
console.log("Invalid JSON: ", message.data);
return;
}
if (json.type === "color") {
myColor = json.data;
status.text(myName + ": ").css("color", myColor);
input.removeAttr("disabled").focus();
} else if (json.type === "history") {
for (var i = 0; i < json.data.length; i++) {
addMessage(
json.data[i].author,
json.data[i].text,
json.data[i].color,
new Date(json.data[i].time)
);
}
} else if (json.type === "message") {
input.removeAttr("disabled");
addMessage(
json.data.author,
json.data.text,
json.data.color,
new Date(json.data.time)
);
} else {
console.log("Hmm..., I've never seen JSON like this:", json);
}
};
input.keydown(function (e) {
if (e.keyCode === 13) {
var msg = $(this).val();
if (!msg) {
return;
}
connection.send(msg);
$(this).val("");
input.attr("disabled", "disabled");
if (myName === false) {
myName = msg;
}
}
});
setInterval(function () {
if (connection.readyState !== 1) {
status.text("Error");
input
.attr("disabled", "disabled")
.val("Unable to communicate with the WebSocket server.");
}
}, 3000);
function addMessage(author, message, color, dt) {
content.prepend(
'<p><span style="color:' +
color +
'">' +
author +
"</span> @ " +
(dt.getHours() < 10 ? "0" + dt.getHours() : dt.getHours()) +
":" +
(dt.getMinutes() < 10 ? "0" + dt.getMinutes() : dt.getMinutes()) +
": " +
message +
"</p>"
);
}
});
- front
<?php
include("layout/header.php"); ?>
<style>
p {
line-height: 18px;
}
div {
width: 500px;
margin-left: auto;
margin-right: auto;
}
#content {
padding: 5px;
background: #ddd;
border-radius: 5px;
overflow-y: scroll;
border: 1px solid #CCC;
margin-top: 10px;
height: 160px;
}
#input {
border-radius: 2px;
border: 1px solid #ccc;
margin-top: 10px;
padding: 5px;
width: 400px;
}
#status {
width: 88px;
display: block;
float: left;
margin-top: 15px;
}
</style>
</head>
<body>
<div id="content"></div>
<div>
<span id="status">Connecting...</span>
<input type="text" id="input" disabled="disabled" />
</div>
<script src="./client.js"></script>
</body>
</html>
<?php include("layout/footer.php");?>
- 결과화면
참고 페이지
'프로그래밍' 카테고리의 다른 글
rufus로 ubuntu iso 부팅파일 만든 usb 복구 (0) | 2023.07.05 |
---|---|
[Linux] 리눅스 외부 연동 방법 (feat VM VirtualBox) (0) | 2023.05.22 |
[Linux] CentOS 아파치 스프링부트 내장톰캣 연동 로드밸런싱 (0) | 2023.05.22 |
[Linux] CentOS 스프링부트 프로젝트 배포를 위한 설치 - 1 (0) | 2023.05.16 |
[Linux] 우분투 Apache, tomcat 연동 (feat. mod_jk) (0) | 2023.05.09 |