똑같은 삽질은 2번 하지 말자

(Node.js)Sokcet 통신을 이용한 1:1 chat 본문

Node

(Node.js)Sokcet 통신을 이용한 1:1 chat

곽빵 2019. 10. 25. 14:08

Socket 통


 

       Server와 Client가 특정 Port를 통해 실시간으로 양방향 통신을 하는 방식

 

Socket통신은 Http 통신과 달리 Server와 Client가 특정 Port를 통해 연결을 성립하고 있어 실시간으로 양방향 통신을 하는 방식입니다. Client만 필요한 경우에 요청을 보내는 Http 통신과 달리 Socket 통신은 Server 역시 Client로 요청을 보낼 수 있으며, 계속 연결을 유지하는 연결지향형 통신이기 때문에 실시간 통신이 필요한 경우에 자주 사용됩니다. 예를 들면, 실시간 Streaming 중계나 실시간 채팅과 같이 즉각적으로 정보를 주고받는 경우에 사용합니다. 예를 들어 실시간 동영상 Streaming 서비스를 Http 통신으로 구현하였다고 가정하겠습니다. 이러한 경우에 사용자가 서버로 동영상을 요청하기 위해서는 동영상이 종료되는 순간까지 계속해서 Http 통신을 보내야 하고 이러한 구조는 계속 연결을 요청하기 때문에 부하가 걸리게 됩니다. 그러므로 이러한 경우에는 Socket을 통해 구현하는 것이 적합합니다.

 

 

 

[ Socket 통신의 특징 ]

  • Server와 Client가 계속 연결을 유지하는 양방향 통신이다.

  • Server와 Client가 실시간으로 데이터를 주고받는 상황이 필요한 경우에 사용된다.

  • 실시간 동영상 Streaming이나 온라인 게임 등과 같은 경우에 자주 사용된다.

var socketio = require('socket.io');

var io = socketio.listen(server);
console.log('socket.io 요청을 받아들일 준비가 되었습니다.');

 기존에 server에다가 socket.io 외장모듈을 씌운다.

 

var login_ids = {};

// 소켓은 기본적으로 이벤트 기반
// 클라이언트로 부터 connect 요청이 들어왔을때,
io.sockets.on('connection', function (socket) {
    console.log('connection info -> ' +
        JSON.stringify(socket.request.connection._peername));
    // javascript 객체로 되어있는 json 문자열 형태로 바꿔주는 함수

    socket.remoteAddress = socket.request.connection._peername.address;
    socket.remotePort = socket.request.connection._peername.port;

    socket.on('login', function (input) {
        console.log('login 받음 ->' + JSON.stringify(input));

        login_ids[input.id] = socket.id;
        socket.login_id = input.id;

        sendResponse(socket, 'login', 200, 'ok');
    });
	// 클라이언트로부터 메세지를 받았을때,
    socket.on('message', function (message) {
        console.log('message 받음: ' + JSON.stringify(message));

        if (message.recepient == 'ALL') {
            console.log('모든 클라이언트에게 메시지 전송함.');
            io.sockets.emit('message', message);
        } else { //login_ids 에 저장되어있는 값이 있다면 로그인된 아이디
            if (login_ids[message.recepient]) {
                console.log('socket : ' + login_ids[message.recepient]);
                // connected는 소켓번호를 안다면 연결된 소켓을 얻어올 수 있다.
                io.sockets.connected[login_ids[message.recepient]].emit('message', message);

                sendResponse(socket, 'message', 200, 'OK');
            } else {
                sendResponse(socket, 'message', 400, '상대방 ID를 찾을 수 없음');
            }
        }
    });
});
// 잘 반응됬는지 반응정보를 클라이언트에게 전달하기 위해 만들어준 메소드
function sendResponse(socket, command, code, message) {
    var output = {
        command: command,
        code: code,
        message: message
    };
    socket.emit('response', output);
}

connection 이벤트는 연결 요청 이벤트가 들어왔을때, 이고 콜백 매개변수로 들어온 socket은 연결된 socket 이다.

 

이 밑은 클라이언트 

<!DOCType html>

<html>

<head>
    <meta charset='utf-8'>
    <title>채팅 클라이언트</title>

    <script src="jquery-3.1.1.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>

    <script>
        var socket;
        $(function() {

        });

        function connect() {
            var host = $('#hostInput').val();
            var port = $('#portInput').val();

            connectToServer(host, port);
        }

        function connectToServer(host, port) {
            var url = 'http://' + host + ":" + port;
            var options = {
                forceNew: true
            };
            socket = io.connect(url, options);
            socket.on('connect', function() {
                println('웹소켓 서버에 연결됨.' + url);
            });
            socket.on('disconnect', function() {
                println('웹소켓 서버 종료됨.');
            });

            socket.on('message', function(message) {
                $('#results').append('<p>' + JSON.stringify(message) + '</p>');
            });

            socket.on('response', function(input) {
                println('응답 -> ' + JSON.stringify(input));
            });
        }

        function login() {
            // login 기능 정의 하면서 logout 도 만들어보기 
            var id = $("#idInput").val();
            var password = $("#passwordInput").val();
            var alias = $("#aliasInput").val();
            var today = $("#todayInput").val();

            var output = {
                id: id,
                password: password,
                alias: alias,
                today: today
            };

            socket.emit('login', output);

        }

        function logout() {

        }

        function send() {
            var sender = $("#sednerInput").val();
            var recepient = $("#recepientInput").val();
            var data = $("#dataInput").val();
            var message = {
                sender: sender,
                recepient: recepient,
                command: 'chat',
                type: 'text',
                data: data
            };
            socket.emit('message', message);

        }

        function println(data) {
            console.log(data);
            $('#results').append('<p> 수신 -> ' + data + '</p>');
        }

    </script>
</head>

<body>
    <h3>채팅 클라이언트 03</h3>
    <br>
    <div>
        <h5>서버 연결</h5>

        <input type="text" id="hostInput" value="localhost">
        <input type="text" id="portInput" value="3000">
        <input type="button" id="connectButton" value="연결하기" onclick="connect();">
    </div>
    <br>
    <br>
    <div>
        <h5>로그인 기능.</h5>

        <input type="text" id="idInput" value="test01">
        <input type="password" id="passwordInput" value="123456">
        <input type="text" id="aliasInput" value="소녀시대">
        <input type="text" id="todayInput" value="좋은 날!">
        <input type="button" id="loginButton" value="로그인" onclick="login();">
        <input type="button" id="logoutButton" value="로그아웃" onclick="logout();">
    </div>
    <div>
        <h5>메시지 전송</h5>
        <div>
            <span>
                보내는 사람:
            </span>
            <input type="text" id="senderInput" value="test01">
        </div>
        <div>
            <span>
                받는 사람:
            </span>
            <input type="text" id="recepientInput" value="ALL">
        </div>
        <div>
            <span>
                전송할 데이터:
            </span>
            <input type="text" id="dataInput" value="안녕!">
        </div>
        <br>
        <input type="button" id="sendButton" value="전송" onclick="send();">

    </div>
    <hr>
    <p>결과</p>
    <div id="results"></div>
</body>

</html>
Comments