본문 바로가기

블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기

[121일차] WebSocket ws로 Server 구현

반응형

 

Http 서버 -> 인터페이스 기능을 수행한다 

 

그동안 만든 js 역할

server.js => 인터페이스 기능 (리모콘과 비슷) 

network.js => 데이터 연결연결 해서 정보 공유, 소통할 수 있는 백앤드 

block.js => 나의 블록들을 저장하는 형태 만드는 공간 

 

 

오랫만에 js 연습

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
    <script type="text/javascript">
        
    let callback = (number,cb)=>{
        // setTImeout = 비동기 
        setTimeout(()=>{
            let sum = 0;
            for (let i = 0; i<number; i++){
                sum += i
            }
            cb(sum)
        },1000)
    }
        
    console.log('1')

    callback(10, (a)=>{console.log(a)})
    
    console.log('2')

    </script>

</body>
</html>

=> console.log 찍히는 순서 

1
2
45

 

 

 

 


 

 

 

 

src2 > network2.js 

const WebSocket = require('ws')

// 내 자신을 websocket server로 만들겠다. 
function wsInit(){
    const server = new WebSocket.Server({port:6005})
    // 인자값을 ws로 받겠다. 
    server.on('connection',(ws)=>{
        ws.on('message',(message)=>{
            console.log(`reveived:${message}`)
        })

    })    
}

wsInit()

=> node network2.js 실행해도 무언가 실행이 안된다 -> console.log 차례로 찍어보면 

const WebSocket = require('ws')

// 내 자신을 websocket server로 만들겠다. 
function wsInit(){
    console.log(1)
    const server = new WebSocket.Server({port:6005})
    // 인자값을 ws로 받겠다. 
    server.on('connection',(ws)=>{
        console.log(2)
        ws.on('message',(message)=>{
            console.log(3)
            console.log(`reveived:${message}`)
        })
        console.log(4)
        ws.send('somethinggg')
    })    
    console.log(5)
}

wsInit()

1, 5 만 뜬다 

connection 이라는 이벤트를 받을 수 있도록 처리를 해줘야함. 

 

 

src2 > network3.js 생성 = >  Client 쪽 코드를 작성해보기 

const WebSocket = require('ws')
const ws = new WebSocket('ws://localhost:6005')

ws.on('open',()=>{
    ws.send('something')
})

ws.on('message',(message)=>{
    console.log(`received:${message}`)
})

 

=> 그 다음 network2 / network3.js server on 해보면 

 

 

 

 

 

network2.js 서버 꺼놓고 

network3.js 아래처럼 수정해서 보면

const WebSocket = require('ws')
const ws = new WebSocket('ws://localhost:6005')

ws.on('open',()=>{
    ws.send('something')
})

ws.on('error', ()=>{
    console.log(`에러 발생`)
})


ws.on('message',(message)=>{
    console.log(`received:${message}`)
})

 

 

network3.js Client server쪽에서 connect() 연결하는 코드는 요것 ↓↓↓↓

const ws = new WebSocket('ws://localhost:6005')

 

 

Server 쪽 module 로 wsInit export 

const WebSocket = require('ws')

// 내 자신을 websocket server로 만들겠다. 
function wsInit(){
    console.log(1)
    const server = new WebSocket.Server({port:6005})
    // 인자값을 ws로 받겠다. 
    server.on('connection',(ws)=>{
        console.log(2)
        ws.on('message',(message)=>{
            console.log(3)
            console.log(`reveived:${message}`)
        })
        console.log(4)
        ws.send('somethinggg')
    })    
    console.log(5)
}

module.exports={
    wsInit,
}

 

 

 

여러대의 서버가 connection하게 되면 모든 사람에게 ws.send를 하게 됨 , 특정 ws(Client)에게 특정 정보 전달을 위해=> ws를 배열에 담기 시작함 

 

const WebSocket = require('ws')


let sockets=[]
// 내 자신을 websocket server로 만들겠다. 
function wsInit(){
    console.log(1)
    const server = new WebSocket.Server({port:6005})
    // 인자값을 ws (Client 정보) 로 받겠다. 
    server.on('connection',(ws)=>{
        init(ws)
    })    
}

function init(ws){
    sockets.push(ws)
}

module.exports={
    wsInit,
}

 

 

network2.js 

const WebSocket = require('ws')


let sockets=[]
// 내 자신을 websocket server로 만들겠다. 
function wsInit(){
    console.log(1)
    const server = new WebSocket.Server({port:6005})
    // 인자값을 ws (Client 정보) 로 받겠다. 
    server.on('connection',(ws)=>{
        init(ws)
    })    
}

function init(ws){
    sockets.push(ws)
    initMessageHandler(ws)
}

function initMessageHandler(ws){
    ws.on('message',data=>{
        console.log('data=',data)
    })
}

wsInit()

module.exports={
    wsInit,
}

 

network3.js 

const WebSocket = require('ws')
const ws = new WebSocket('ws://localhost:6005')

ws.on('open',()=>{
    ws.send('something')
    ws.send('서버야 받아봐라 ~ ')
})

ws.on('error', ()=>{
    console.log(`에러 발생`)
})


ws.on('message',(message)=>{
    console.log(`received:${message}`)
})

-> data.toString() 만 붙여주면 ok ! 

 

 

 

{} 객체 형태 보내보기 

network3.js 

ws.on('open',()=>{
    ws.send(`{"name":"emily"}`)
})

 

network2.js 

받을 때 JSON.parse 로 string -> json type으로 변환 

function initMessageHandler(ws){
    ws.on('message',data=>{
        // console.log('data=',data)
        // console.log(data.toString())
        console.log(JSON.parse(data))
    })
}

** 주의점 JSON.parse() 는 '' 작은따옴표는 parse를 안해준다 ! 

{} 객체 감싸는 ' ' or ` ` 

string을 감싸는 " "  요렇게 가능 

 

 

Client 쪽에서 아예 json.string() 으로 바꿔서 던져주기 

 

network3.js 

보낼 때 string으로 던지기 

ws.on('open',()=>{
    let obj = {name:"emily"}
    let rst = JSON.stringify(obj)
    ws.send(rst)
})

network2.js

받을 때 JSON.parse로 string => json으로 받기 

function initMessageHandler(ws){
    ws.on('message',data=>{
        // console.log('data=',data)
        // console.log(data.toString())
        console.log(JSON.parse(data))
    })
}

 

 

network2.js에서 JSON.stringify 해주는 write 함수 따로 만들기 

 

network3.js

ws.on('open',()=>{
    let obj = {name:"emily"}
    write(ws,obj)
})

function write(ws, message){
    ws.send(JSON.stringify(message))
}

 

 

 

network3.js 

ws.on('open',()=>{
    let obj = {
        type:'msg',
        data:'안녕하세요.'
    }
    write(ws,obj)
})

function write(ws, message){
    ws.send(JSON.stringify(message))
}

보내는 obj를 위처럼 type, data로 분리해서 보내기 

 

network2.js

받을 때 type에 따라 switch문을 이용해서 각각 다른 명령 실행 가능 

function initMessageHandler(ws){
    ws.on('message',data=>{
        const message = JSON.parse(data)
        console.log(`parsed data=`,JSON.parse(data))
        
        switch(message.type){
            case "msg":
                console.log(message.data)
                console.log('type=msg 일 경우 data 출력 ')
            break;
        }
        
    })
}

 

 

type 추가해보기 

 

network3.js

ws.on('open',()=>{
    let obj = {
        type:'msg',
        data:'안녕하세요.'
    }
    write(ws,obj)

    let obj2 = {
        type:'send',
        data:'데이터를 보내겟습니다.'
    }

    write(ws,obj2)
})

 

network2.js

function initMessageHandler(ws){
    ws.on('message',data=>{
        const message = JSON.parse(data)
        console.log(`parsed data=`,JSON.parse(data))
        
        switch(message.type){
            case "msg":
                console.log(message.data)
                console.log('type=msg 일 경우 data 출력 ')
            break;
            case "send":
                console.log(message.data)
                console.log(`type=send 일 경우 data 출력`)
            break;
        }
        
    })
}

 

 

network2.js 스트링을 변수에 넣어 사용하기 (나중에 오류 찾기 수월) 

const MSG = "msg"
const SEND = "send"

function initMessageHandler(ws){
    ws.on('message',data=>{
        const message = JSON.parse(data)
        console.log(`parsed data=`,JSON.parse(data))
        
        switch(message.type){
            case MSG:
                console.log(message.data)
                console.log('type=msg 일 경우 data 출력 ')
            break;
            case SEND:
                console.log(message.data)
                console.log(`type=send 일 경우 data 출력`)
            break;
        }
        
    })
}

 

변수대신 객체로 묶어서 사용도 가능 ! ↓↓ 요로코롬 

const messageAction ={
    MSG:"msg",
    SEND:"send"
}

function initMessageHandler(ws){
    ws.on('message',data=>{
        const message = JSON.parse(data)
        console.log(`parsed data=`,JSON.parse(data))
        
        switch(message.type){
            case messageAction.MSG:
                console.log(message.data)
                console.log('type=msg 일 경우 data 출력 ')
            break;
            case messageAction.SEND:
                console.log(message.data)
                console.log(`type=send 일 경우 data 출력`)
            break;
        }
        
    })
}

 

여기서 특정 case 안의 내용이 길 ~ 면 함수로 빼서 사용

function initMessageHandler(ws){
    ws.on('message',data=>{
        const message = JSON.parse(data)
        console.log(`parsed data=`,JSON.parse(data))
        
        switch(message.type){
            case messageAction.MSG:
                console.log(message.data)
                console.log('type=msg 일 경우 data 출력 ')
            break;
            case messageAction.SEND:
                console.log(message.data)
                console.log(`type=send 일 경우 data 출력`)
            break;
            case messageAction.RESPONSE_BLOCK:
                handleBlockResponse()
            break;
        }
        
    })
}

function handleBlockResponse(){
    // 명령어 실행 
}

 

 

 

client server close 경우

 

network2.js

function initErrorHandler(ws){
    // ERROR 났거나 server 종료했거나 
    ws.on('close', ()=>{
        console.log('closed !? ')
        // 나간 client socket 제외시켜야함 
        sockets.splice(sockets.indexOf(ws),1)
    })
}

=> 양쪽 server on => client server off -> 

요렇게 나옴 ! 

 

 

 

ERROR 

function initErrorHandler(ws){
    // ERROR 났거나 server 종료했거나 
    ws.on('close', ()=>{
        console.log('closed !? ')
        // 나간 client socket 제외시켜야함 
        sockets.splice(sockets.indexOf(ws),1)
    })
    ws.on('error',()=>{
        console.log('error~~~~~~')
        // 에러가 난 사람에게도 보낼 필요가 없어서 
        sockets.splice(sockets.indexOf(ws),1)
    })
}

 

 

 

 

CLOSE & ERROR 에서 사용되는 코드 똑같은 것을 함수로 빼기 

function initErrorHandler(ws){
    // ERROR 났거나 server 종료했거나 
    ws.on('close', ()=>{
        console.log('closed !? ')
        // 나간 client socket 제외시켜야함 
        closeConnetcion(ws)
    })
    ws.on('error',()=>{
        console.log('error~~~~~~')
        // 에러가 난 사람에게도 보낼 필요가 없어서 
        closeConnetcion(ws)
    })
}

function closeConnetcion(ws){
    console.log(`connection close ${ws}`)
    sockets.splice(sockets.indexOf(ws),1)
}

 

 

반응형