Socket.IO
- socket.io는 웹소켓을 이용해 클라이언트에 실시간으로 데이터를 전송한다.
- socket.io는 Socket을 구현한것으로 WebSocket 개발을 쉽게 하기 위한 것이다.
- 클라이언트에서 Event Listener로 새로운 정보를 받아 정보를 업데이트할 수 있다.
Socket.IO는 실시간 웹 애플리케이션을위한 JavaScript 라이브러리입니다. 웹 클라이언트와 서버간에 실시간 양방향 통신이 가능합니다. 브라우저에서 실행되는 클라이언트 측 라이브러리와 Node.js 용 서버 측 라이브러리의 두 부분으로 구성됩니다.
socket.io 활용되는 곳
- 실시간 분석, 메시지, 채팅
- 바이너리 스트리밍, 문서 공동작업 등
[특징]
- Node.js 라이브러리로 실시간 웹 기술을 손쉽게 사용할 수 있는 모듈
- Websock, Polling, Streaming 등 다양한 방법을 하나의 API로 추상화
- 브라우저의 종류에 상관없이 실시간 웹 구현 가능
[작동방식]
Socket.IO는 웹 브라우저와 웹 서버의 종류와 버전을 파악하여 가장 적합한 기술을 선택하여 사용한다.
- 만약 브라우저에 FlashSocket이라는 기술을 지원하는 플러그인이 설치되어 있으면 그것을 사용하고
- 플러그인이 없으면 AJAX Long Polling방식을 사용하도록 한다.
socket.io 모듈 설치
- npm install socket.io
서버 측 socket.io 설정 작업
1. http 서버 생성
import { Server } from 'socket.io';
const server = http.createServer(app);//http 서버생성(nodejs에 내장되어있는 http package )
2. socket.io 객체 생성 및 구동
const io = new Server(server)
3. 주요 이벤트 처리
io.connect('connect', (socket)=>{
socket.on('disconnect', (reason)=>{...코드...});
socket.on('error', (error)=>{...코드...});
socket.on('사용자정의이벤트', (data)=>{...코드...});
});
- connect 이벤트를 제외하곤, 콜백함수의 매개변수로 들어온 socket객체에 이벤트 처리를 해주는 점에 주의하자!
1) connect: 연결 성공
2) disconnect: 연결 종료
3) error: 에러 발생
4) 그외 : 사용자 정의 이벤트
- 첫번째 매개변수: 연결할 http서버를 설정
- 두번째 매개변수: 객체{키: 값, ... } 형태로 각종 옵션을 설정한
다
4. 데이터 전송 to 클라이언트: 사용자 정의 이벤트 발생
socket.emit('이벤트 이름', '클라이언트에게 전송할 데이터 내용');
- emit()메서드를 통해 클라이언트에게 "데이터"를 보낼 수 있다.
- 클라이언트에서는 "이벤트이름"으로 데이터를 받아 처리할 수 있다.
#3 클라이언트 측 socket.io 설정 작업
1. 서버 socket접속용 객체 생성 및 연결
const socket = io();
2. 이벤트 처리(연결/종료/에러/데이터 수신 등)
socket.on('connect', ()=>{... 코드 ...});
socket.on('disconnect', (reason)=>{... 코드 ...});
socket.on('error', (error)=>{... 코드 ...});
socket.on('사용자정의이벤트', (data)=>{... 코드 ...});
1) connect: 연결 성공
2) disconnect: 연결 종료
3) error: 에러 발생
4) 그외 : 사용자 정의 이벤트 - 개발자가 서버에 데이터 전송시 '이름표'를 달고 보내는 이벤트다.
3. 데이터 전송 to 클라이언트: 사용자 정의 이벤트 발생
socket.emit('이벤트 이름', '서버에게 보낼 데이터 내용');
- emit()메서드를 통해 서버에게 "데이터"를 보낼 수 있다.
- 서버에서는 "이벤트이름"으로 데이터를 받아 처리할 수 있다.
-서버에서 받을때 이벤트명을 똑같이 해야된다
-문자,객체,숫자,함수 등등 여러가지를 보낼수있다(갯수제한 x ) , 단 함수는 맨 마지막에
# 전체 샘플 소스코드
- 서버측 소스코드
import path, { parse } from 'path';
import express from "express";
import http from "http";
import WebSocket, { WebSocketServer } from 'ws'; //websocket은 브라우저에서 제공해줌
import { Socket } from 'dgram';
import { Server } from 'socket.io'; //socket.io는 별도 라이브러리 설치필요
const __dirname = path.resolve();
const app = express();
//pug 페이지 렌더링 하기위해 pug설정
app.set("view engine" , "pug");
app.set("views", __dirname + "/views");
app.get("/" , (req,res)=> res.render("home"));
app.use("/public" ,express.static(__dirname+"/public"));
//socket.io
const server = http.createServer(app);//http 서버생성(nodejs에 내장되어있는 http package )
const io = new Server(server)
io.on("connection" , (socket)=>{
socket.on("enter_room", (roomName,func)=>{//나포함 방에들어오는 브라우저마다 실행 (socket.on으로 enter_room 이벤 트 받기)
// console.log(socket.rooms)//socket이 어떤방에 있는지 알기위해 socket.rooms
socket.join(roomName) //해당방에 조인
func()
socket.to(roomName).emit("welcome" , socket.nickname ,countInRoom(roomName) ) //welcome이라는 이벤트를 roomName에있는 모든사람에게 전달(자신제외) //countInRoom:방에 몇명있는지 출력
io.sockets.emit("room_change" ,publicRoom()) //public 방이 만들었는지,사라졌는지 여부를 전달(존재하는 모든 sockets 에게전달)
})
socket["nickname"] = "Anonymous"
socket.on("nickname" , (nickname)=>{ //브라우저에서 보낸 닉네임 설정하기
socket["nickname"] = nickname
})
socket.on("offer" , (offer,roomName) =>{ //offer이벤트를 받음
socket.to(roomName).emit("offer" , offer)
})
socket.on("answer" , (answer,roomName) =>{ //offer이벤트를 받음
socket.to(roomName).emit("answer" , answer)
})
socket.on("disconnecting" , ()=>{ //접속이 중단되었지만 방을 나가지않은상태
socket.rooms.forEach( roomName => socket.to(roomName).emit("bye" , socket.nickname ,countInRoom(roomName)-1)) //romms에 있는 browser 전부에게 bye 이벤트를 보냄(떠나기직전이므로-1)
}) //countInRoom:방에 몇명있는지 출력->아직 방을떠나지않기에 room에 접근가능
socket.on("disconnect",()=>{ //완전 접속이 끊어진경우
io.sockets.emit("room_change" ,publicRoom()) //public 방이 만들었는지,사라졌는지 여부를 전달(존재하는 모든 sockets 에게전달):브로드캐스트
})
socket.on("new_message" , (message,roomName,func)=>{ //브라우저한테 메시지받고 , 그메시지를 다른브라우저에게 뿌리기 (roomName방으로)
socket.to(roomName).emit("new_message" , `${socket.nickname}: ${message}`)
func()
})
console.log(io.sockets.adapter.rooms) //private room + public room //io.sockets.adapter = adapter in memory -> mongdb dapter로 바꿔줘야됨
})
//공개방 구하기
function publicRoom(){
const sids = io.sockets.adapter.sids //sids는 private룸만 가지고있음
const room = io.sockets.adapter.rooms //room는 private,public 룸 전부 가지고있음
const publicRoom = [] //공개방 구하기
room.forEach((value,key)=>{
if(sids.get(key)=== undefined){
publicRoom.push(key) //존재하지않다면 그건 public 룸임 (room id를 socket id에서 찾을수없으면 -> public room)
}
})
return publicRoom
}
function countInRoom(roomName){//해당방에 몇명 인원이있는지 확인
return io.sockets.adapter.rooms.get(roomName)?.size;
}
server.listen(3000 , ()=> {console.log("hello")})//localhost는 동일한 port에서 http,ws,socket.io request 둘다 처리가능
- 클라이언트측(브라우저) 소스코드
body
header
h1 ZOOM
main
div#welcome
form
input(placeholder="room name" , required , type="text")
button Enter Room
h4 Open Rooms:
ul
div#room
h2
ul
form#nick
input(placeholder="nickname" , required , type="text")
button 설정
form#msg
input(placeholder="message" , required , type="text")
button 전송
script(src="/socket.io/socket.io.js")
script(src="/public/js/app.js")
const socket = io(); //io function은 알아서 socket.io를 실행하고있는 서버를 찾음
const welcome = document.getElementById("welcome")
const form = welcome.querySelector("form")
const room = document.getElementById("room")
room.hidden = true
let roomName
function addMessage(message) {
const ul = room.querySelector("ul")
const li = document.createElement("li")
li.innerText = message
ul.appendChild(li)
}
form.addEventListener("submit",(event)=>{ //event 이름, 서버에 보낼 data : websocket처럼 string만 보낼필요x
event.preventDefault()
const input = form.querySelector("input")
roomName = input.value //방이름
let h2 = room.querySelector("h2")
h2.innerText = roomName
socket.emit("enter_room", input.value , ()=>{ //방입장(enter_room 이라는 event를 emit)
// input.value(방이름)을 서버로 값을 내보냄(:websocket고 다르게 object도 전송가능)(갯수제한없음 ->인자를 늘리면됨 )
room.hidden = false //argument로 서버에서 실행할수있는 callback 함수등록(서버에서 호출되지만 실행은 프론트에서)(백엔드에서 이 함수 호출시 argument도 전송가능)
welcome.hidden = true
const msgForm = room.querySelector("#msg")
const nickForm = room.querySelector("#nick")
msgForm.addEventListener("submit" , (event)=>{
event.preventDefault()
const input = room.querySelector("#msg input")
const value = input.value
socket.emit("new_message" , input.value , roomName , ()=>{//메시지 보내기
addMessage(`me: ${value}`) //채팅이 화면에 보이게 하기위해
})
input.value = ""
})
nickForm.addEventListener("submit" , (event)=>{ //닉네임 설정
event.preventDefault()
const input = room.querySelector("#nick input")
socket.emit("nickname" , input.value)
})
})
input.value = ""
})
socket.on("welcome",(user , num)=>{ //welcome이벤트 받음 user=접속유저 , num=채팅방인원
let h2 = room.querySelector("h2")
h2.innerText = `${roomName}(${num})`
addMessage(`${user} join room`)
})
socket.on("bye",(user , num)=>{ //bye이벤트 받음 user=나간유저 , num=채팅방인원
let h2 = room.querySelector("h2")
h2.innerText = `${roomName}(${num})`
addMessage(`${user} left room`)
})
socket.on("new_message",(msg)=>{ //메시지받기 (다른브라우저->서버 -> 내브라우저)
addMessage(msg)
})
socket.on("room_change",(rooms)=>{ //방이 사라지고 생길떄마다 -> ui 바꿔줌
const roomList = welcome.querySelector("ul")
roomList.innerHTML=""
if(rooms.length === 0){
roomList.innerHTML=""
return
}
rooms.forEach(room =>{
const li = document.createElement("li")
li.innerText = room
roomList.append(li)
})
})
socket.io와 websocket의 차이점
1. 설치
둘 다 서버에서는 모듈 설치가 필요하지만 ws는 웹소켓 표준이라 클라이언트에 추가적인 설치를 요구하지 않습니다.
2. 데이터형식
socket.io:이벤트명과 데이터를 명확하게 구분하고 모든자료형을 주고받을수있음(문자,객체,숫자 등등), 또한 갯수제한x
ws는 string 자료형 하나로 데이터를 주고 받습니다. 이벤트명도 데이터에 포함해서 받으므로 데이터를 parsing하는 과정이 필요합니다.이를 활용하기 위해 주로 JSON.parse나 JSON.stringify함수를 사용
3. room,broadcast
socket.io: room과 broadcast와 같은 기능지원 (broadcast:자신을 제외한 사용자에게 데이터를 보내는기능)
ws는 해당 기능을 전부 직접 구현해야된다
4. 연결
sockey.io:연결이 끊겼을떄 계속 연결할려고 시도함
ws:연결이 끊어졌을 때 연결을 지속할려면 직접구현해야됨
5. 이벤트명
socket.io : 직접 이벤트명을 적어서 데이터를 전송
websocket은 message이벤트로만 데이터를 전송
참고:Node.js(Express)와 Socket.io | PoiemaWeb
Node.js(Express)와 Socket.io | PoiemaWeb
WebSocket, Socket.io를 사용한 실시간 채팅 애플리케이션
poiemaweb.com
참고:Socket.IO
Socket.IO
Reliable Rest assured! In case the WebSocket connection is not possible, it will fall back to HTTP long-polling. And if the connection is lost, the client will automatically try to reconnect.
socket.io
참고:
socket.io
node.js realtime framework server
www.npmjs.com
'Web Browser' 카테고리의 다른 글
WebRTC (0) | 2021.12.21 |
---|---|
MediaDevices (0) | 2021.12.21 |
web socket (0) | 2021.12.18 |
http통신 , socket통신 (0) | 2021.12.18 |
DOM , DOM Manipulation (0) | 2021.11.22 |