본문 바로가기

코딩/Today I Learn

Zoom 클론코딩 #2웹소켓

728x90

프로토콜 HTTP와 WEBSOCKET의 차이점

 

HTTP : stateless

backend가 유저를 기억하지 못한다는 뜻  ,reply만 가능함

http://

 

WSS:  양방향

악수처럼 진행됨 처음에 req 보내고 accept하면 연결은 성립되는 것 

연결되어있으면 브라우저와 서버는 어느 때나 메세지를 보낼 수 있음 

브라우저에는 내장된 websocket api가있음

wws://

 

 

웹소켓의 기본이되는 ws

npm i ws로 설치 

특징:부가적인기능 없음 완전 기본코드

 

 

ws서버와 express서버를 합칠 것임 

항상 이런식으로 코드를 두개 작성하지 않아도되지만

두개 모두 같은 포트에서 작동하게하고싶어서 

http서버 위에 ws서버를 만들기위함 

http,ws reqeust를 같은 포트에서 처리 할 수 있음

 

 

import http from "http";
import WebSocket from "ws";
import express from "express";

const app = express();

app.set("view engine", "pug");
app.set("views", __dirname + "/views");

app.use("/public", express.static(__dirname + "/public"));

app.get("/", (req,res)=> res.render("home"));
app.get("/*",(req,res)=>res.redirect("/"));

const hanldeListen =()=> console.log("Listening on http://localhost:3000");

const server = http.createServer(app);

const wss = new WebSocket({server});

server.listen(3000, hanldeListen)

--Big Issue---
"ws": "^8.2.3" 버전부터는
Websocket.Server 가 아니라 WebSocketServer 입니다.
아래 문서를 참고하세요 https://www.npmjs.com/package/ws

내 버전은 8.1.3

 

프론트엔드에서는 웹소켓 설치할 필요없음

백엔드와 연결만하면 됨

wss.on작동은 이벤트핸들러와 매우흡사함   

on method는 backend에 연결된 사람의 정보를 제공해줌 socket(서버와 브라우저의연결)

 

wss.on("connection",(socket)=>{
    console.log(socket);
});

연결이 없기에 지금은 아무런 활동이 일어나지 않음 

프론트엔드에 백엔드와 연결해달라고해야함 

 

연결하는 법 

https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket

 

 

app.js
const socket = new WebSocket(`ws://${window.location.host}`);
//모바일에서는 localhost:3000이 없으니까 해당 브라우저에서 주소 가져오기 
window.location.host

 

server.js의 socket은 연결된 브라우저를 뜻함 

app,js 의 socket은 서버로의 연결 

나는 헷갈려서 각각 backSocket , frontSocket 으로 지정함 

 

socket에 있는 메서드를 사용해보자 서버,ws의 매서드 아님 

메세지를 보내긴했지만 

프트엔드에서 받지않아서 안뜸 

server.js

wss.on("connection", (socket)=> {
    console.log("Connected to Browser ✅"); //브라우저열면
    socket.send("hello!!");
    socket.on("close", () =>console.log("Disconnected from Browser ❌"));//브라우저 닫으면
});

 

 

app.js

const socket = new WebSocket(`ws://${window.location.host}`);

socket.addEventListener("open", ()=>{
    console.log("Connected to Server ✅") //서버연결되면
});
socket.addEventListener("message", (message)=>{ //send로 보낸게 message이벤트임
    console.log("New message:", message.data,"from the server");
});
socket.addEventListener("close",()=>{
    console.log("Disonnected to Server ❌");//서버 종료하면
})

 

반대로 브라우저에서 서버로 메세지보내기

app.js

setTimeout(()=>{
    socket.send("hello from browser"); 10초후에 보내면
},10000)

 

server.js

wss.on("connection", (socket)=> {  // 버튼을 리스닝하고 이벤트를 받아서 처리한 것과 같다. wws는 전체 서버  
    console.log("Connected to Browser ✅");  /
    socket.on("close", () =>console.log("Disconnected from Browser ❌")); //종료됐을 때 //각 socket(브라우저)에대한 처리 
    socket.on("message", (message)=>{ //메시지 이벤트 받아서 콘솔창에 나타내기
        console.log(message.toString('utf8);
    })
        socket.send("hello!!"); //보내기

});

 

form 만들어서 back으로 보내고 다시 back에서 front로 보내기 

app.js

function handleSubmit(event){
    event.preventDefault();
    const input = messageForm.querySelector("input");
    socket.send(input.value);
    input.value = "";
}

messageForm.addEventListener("submit", handleSubmit);

 

 

server.js

wss.on("connection", (socket)=> {
    console.log("Connected to Browser ✅");
    socket.on("close", () =>console.log("Disconnected from Browser ❌"));
    socket.on("message", (message) => {
        socket.send(message.toString());
    });
});

--- 메세지가 바로 front로 전달됨 하지만 혼자 티카타카는 의미없고 

각가 브라우저에 티키타카가 되도록 삼각형 구도를 만들고싶음 그럴려면 

누가 연결이 되었는지 알아야함 

 

const  sockets = [];

wss.on("connection", (socket)=> { //연결이 된 각 소켓을
    sockets.push(socket); //sockets 배열에 넣고 
    console.log("Connected to Browser ✅");
    socket.on("close", () =>console.log("Disconnected from Browser ❌"));
    socket.on("message", (message) => { //어느곳에서 메세지를 받으면
        sockets.forEach((aSocket) => aSocket.send(message.toString())); //배열 내의 각각 의 소켓에 전달
    });
});

 

html에 나타내기 app.js

socket.addEventListener("message", (message)=>{
    const li = document.createElement("li");
    li.innerText = message.data;
    messageList.append(li);
});

 

닉네임 지정하기

 

html에 위와 같이 form을 만들어서 보내면 

nickname도 li에 추가가된다.

이 두개의 폼에 이름을 붙혀야할 것같다.

json형식으로 socket.send보내기 

 

function makeMessage(type,payload){  
    const msg= {type, payload}  타입과 내용을 객체로받아서
    return JSON.stringify(msg);   문자화해서 백엔드로 보내기 
}

function handleSubmit(event){
    event.preventDefault();
    const input = messageForm.querySelector("input");
    socket.send(makeMessage("new_message", input.value));
    input.value = "";
}

function handleNickSubmit(event){
    event.preventDefault();
    const input = nickForm.querySelector("input");
    socket.send(makeMessage("nickname", input.value));
}

 

백엔드로 javascript object객체를 보내는것은 안좋음 연결하고 싶은 프론트와 백엔드가 자바스크립트 서버가아닐 수잇음 JAVA, GO등 그래서 STRING을 보내고 결정하는 것  

 


wss.on("connection", (socket)=> {
    sockets.push(socket);
    socket["nickname"] ="익명"; //socket에 정보를 추가할 수 있음 //소켓 배열에 여러가지 정보가 있을 텐데 거기에다가
    console.log("Connected to Browser ✅");
    socket.on("close", () =>console.log("Disconnected from Browser ❌"));
    socket.on("message", (msg) => {
        const message = JSON.parse(msg); //객체로 변환해서
        switch(message.type){ //메세지타입이
            case "new_message":     
                sockets.forEach((aSocket) => aSocket.send(`${socket.nickname}:  ${message.payload}`));
                break; //switch문에서 꼭 break를 해줘야 혼선이 안생기고 더이상 찾지 않고 끊음
            case "nickname":
                socket["nickname"] = message.payload;
                break;
        }       
    });
});

 

개선

 

1.

app.js

socket.addEventListener("message", (message)=>{
    const li = document.createElement("li");
    li.innerText = message.data;
    messageList.append(li);
});

 

function handleSubmit(event){
    event.preventDefault();
    const input = messageForm.querySelector("input");
    socket.send(makeMessage("new_message", input.value));
    const li = document.createElement("li");
    li.innerText = `You : ${input.value}`;
    messageList.append(li);
    input.value = "";
}

내가 글을 적고 제출 버튼을 눌렀을 때 화면상에 나타남 

 

이제 글자를 입력하고 제출을하게되면 

front에서 보낸 글자와

서버에서 보낸 글자 두개가 나타남 

 

2.나를 제외한 사람들에게 메세지를 보내고싶음

 

'코딩 > Today I Learn' 카테고리의 다른 글

3.3목  (0) 2022.03.03
Zoom 클론코딩 #3 SoketIO  (0) 2022.03.03
Zoom 클론코딩 #1 환경설정  (0) 2022.02.26
2.19토  (0) 2022.02.26
02.15화  (0) 2022.02.17