작성한 대화방 http://bcho.tistory.com/896 에 이어서 이번에는 1:1 귓속말 대화가 가능한 기능을 추가해보자


귓속말이 가능한 대화방

이번에는 특정 사용자가 다른 사용자에게 귓속말을 보내는 기능을 가지는 대화방을 만들어보자이를 통해서 특정 클라이언트 소켓에 메세지를 어떻게 보내는지를 배울 수 있다.

이 대화방의 기능은 다음과 같다.

  • Ÿ   대화방에 입장하는 손님들은 자동으로 대화명을 부여 받는다.

  • Ÿ   사용자는 대화명을 바꿀 수 있다.

  • Ÿ   사용자는 대화 수신자의 대화명을 선택하여 특정 사용자에게 귓속말을 보낼 수 있다.

코드를 보면서 설명하도록 하자.

app.js

var express = require('express');

var routes = require('./routes');

var http = require('http');

var path = require('path');

 

var app = express();

app.use(express.static(path.join(__dirname, 'public')));

 

var httpServer =http.createServer(app).listen(3000, function(req,res){

    console.log('Socket IO server has been started');

});

// upgrade http server to socket.io server

var io = require('socket.io').listen(httpServer);

 

var socket_ids = [];

var count = 0;

 

function registerUser(socket,nickname){

    // socket_id nickname 테이블을 셋업

    socket.get('nickname',function(err,pre_nick){

        if(pre_nick != undefined ) delete socket_ids[pre_nick];

        socket_ids[nickname] = socket.id

        socket.set('nickname',nickname,function(){

            io.sockets.emit('userlist',{users:Object.keys(socket_ids)});

        });

 

    });

}

 

io.sockets.on('connection',function(socket){

    socket.emit('new',{nickname:'GUEST-'+count});

    registerUser(socket,'GUEST-'+count);

    count++;

 

    socket.on('changename',function(data){

        registerUser(socket,data.nickname);

    });

    socket.on('disconnect',function(data){

        socket.get('nickname',function(err,nickname){

            if(nickname != undefined){

                delete socket_ids[nickname];

                io.sockets.emit('userlist',{users:Object.keys(socket_ids)});

                                

            }// if

        });

     });

    socket.on('send_msg',function(data){

        socket.get('nickname',function(err,nickname){

 

            data.msg = nickname + ' : '+data.msg;

            if(data.to =='ALL') socket.broadcast.emit('broadcast_msg',data); // 자신을 제외하고 다른 클라이언트에게 보냄

            else{

                socket_id = socket_ids[data.to];

                if(socket_id != undefined){

                    io.sockets.socket(socket_id).emit('broadcast_msg',data);

                }// if

            }

            socket.emit('broadcast_msg',data);

        });

    });

});

 

먼저 Express에서 socket.io를 사용할 준비를 하고

특정 사용자 즉 클라이언트에게만 메세지를 보내려면

io.sockets.socket(socket_id).emit

메세드를 사용해야 한다. 해당 클라이언트의 socket_id를 알아야 하며, 우리는 대화명(이하 nickname)을 통해서 특정 사용자에게 메세지를 보낼 것이기 때문에 nickname 에서 socket_id로의 맵핑 테이블이 필요하다.

var socket_ids = []

에서 socket_ids는 nickname to socket.id에 대한 맵핑 정보를 저장한다.

io.sockets.on('connection',function(socket){

    socket.emit('new',{nickname:'GUEST-'+count});

    registerUser(socket,'GUEST-'+count);

    count++;

클라이언트가 접속되면 new 라는 이벤트를 통해서 nickname을 생성해서 보낸다. nickname은 사용자가 접속한 순서대로 GUEST-0,GUEST-1,… 식으로 순차적으로 이름을 배정한다.

다음으로, 새로운 사용자가 추가되었음을 알리고, 현재 사용자 리스트들을 보내야 하는데, 이를 registerUser 메서드에서 수행한다.

function registerUser(socket,nickname){

    // socket_id nickname 테이블을 셋업

    socket.get('nickname',function(err,pre_nick){

        if(pre_nick != undefined ) delete socket_ids[pre_nick];

        socket_ids[nickname] = socket.id

        socket.set('nickname',nickname,function(){

            io.sockets.emit('userlist',{users:Object.keys(socket_ids)});

        });

 

    });

}

먼저 register user에서는 socket.get을 이용하여 현재의 클라이언트 소켓의 nickname을 pre_nick이라는 변수로 읽어온다. 대화명이 바뀔 경우 기존에 socket_ids에 기존의 대화명으로 저장되어 있는 socket.id를 삭제하기 위함이다. 기존의 데이타를 삭제 하였으면, socket_ids에nickname을 Key 값으로 하여, socket.id를 저장한다. 다음. nickname을 해당 socket에 set명령을 이용해서 저장한후에, userlist라는 이벤트를 통해서, 현재 접속된 사용자의 nickname들을 보낸다. 이 nickname들은 socket_ids의 property의 키들로 저장이 되었기 때문에, Object.keys(socket_ids)를 이용하여 nickname 리스트를 추출할 수 있다.

마찬가지로, 대화명이 변경되었을 때에도 registerUser 함수를 이용하여 전체 사용자의 리스트를 업데이트 하여 클라이언트에게 보내준다.

socket.on('changename',function(data){

        registerUser(socket,data.nickname);

    });

만약에 해당 클라이언트가 브라우져를 닫았을 경우에는 대화방을 떠난 것으로 간주하여, ‘disconnect’이벤트에 대해서,

socket.on('disconnect',function(data){

        socket.get('nickname',function(err,nickname){

            if(nickname != undefined){

                delete socket_ids[nickname];

            

현재 socket의 nickname을 읽어서 socket_ids에서 해당 nickname에 해당 하는 데이타를 삭제한 후에,

io.sockets.emit('userlist',{users:Object.keys(socket_ids)});

를 이용하여, 업데이트된 사용자 목록을 다시 클라이언트들이 업데이트 하도록 이벤트를 보낸다.

마지막으로 클라이언트로 부터 대화메세지를 다른 사용자에게 대화 메세지를 보내는 “send_msg” 이벤트가 들어왔을때

socket.on('send_msg',function(data){

        socket.get('nickname',function(err,nickname){

 

            data.msg = nickname + ' : '+data.msg;

에서 처리하는데, 현재 클라이언트의 nickname을 socket.get을 이용해서 읽어와서 보낼 메세지문자열을 “대화명”+”대화내용”으로 만들어서 저장한다.

만약에 전체 메세지인 경우 data.to 가 ‘ALL’로 들어오는데, 이경우 broadcast를 하고

if(data.to =='ALL') socket.broadcast.emit('broadcast_msg',data);

특정 nickname이 data.to에 들어오는 경우 귓속말로 간주하여, nickname을 이용해서 socket_ids로 부터 해당 nickname을 사용하는 클라이언트의 socket.id를 가져온후

socket_id = socket_ids[data.to];

                if(socket_id != undefined){

다음으로, 해당 socket_id로 메세지를 보낸다.

io.sockets.socket(socket_id).emit('broadcast_msg',data);

다음은 위의 서버를 사용하기 위한 HTML 클라이언트 폼이다.

index.html

<html>

<head>

 

    <title></title>

    <script src="/socket.io/socket.io.js"></script>

    <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>

 

</head>

<body>

<b>Send message</b><p>

    Name <input type="text" id="nickname" /> <input type="button" id="changename"value="Change name"/><br>

    To

    <select id="to">

        <option value="ALL">ALL</option>

    </select>

    Message  <input type="text" id="msgbox"/>

    <br>

    <span id="msgs"></span>

 

    <script type="text/javascript">

        var socket = io.connect('http://localhost');

        $('#changename').click(function(){

            socket.emit('changename',{nickname:$('#nickname').val()});

        });

        $("#msgbox").keyup(function(event) {

            if (event.which == 13) {

                socket.emit('send_msg',{to:$('#to').val(),msg:$('#msgbox').val()});

                $('#msgbox').val('');

            }

        });

        socket.on('new',function(data){

            console.log(data.nickname);

            $('#nickname').val(data.nickname);

        });

 

        // 새로운 사용자가 들어오거나사용자가 이름을 바꿨을때 "To" 리스트를 변경함

        socket.on('userlist',function(data){

            var users = data.users;

            console.log(users);

            console.log(data.users.length);

            $('#to').empty().append('<option value="ALL">ALL</option>');

            for(var i=0;i<data.users.length;i++){

                $('#to').append('<option value="'+users[i]+'">'+users[i]+"</option>");

            }

        });

 

        socket.on('broadcast_msg',function(data){

            console.log(data.msg);

            $('#msgs').append(data.msg+'<BR>');

        });

    </script>

</body>

</html>


앞에서 작성한 채팅 프로그램과 크게 다를바는 없으나, new 이벤트와 userlist 이벤트 핸들러가 추가되었다.

‘new’ 이벤트는 채팅방에 들어왔을때, 서버로 부터 대화명과 함께 보내지며, 클라이언트에서는 이 대화명을 받아서, “대화명 창”부분에 세팅 한다.

socket.on('new',function(data){

            console.log(data.nickname);

            $('#nickname').val(data.nickname);

        });

‘userlist’ 이벤트는 현재 대화방에 있는 사용자들의 nickname을 모두 받은 후에, 대화 상대를 지정하는 HTML <select> box 부분에 대화명들을 넣어준다.

socket.on('userlist',function(data){

            var users = data.users;

            console.log(users);

            console.log(data.users.length);

            $('#to').empty().append('<option value="ALL">ALL</option>');

            for(var i=0;i<data.users.length;i++){

                $('#to').append('<option value="'+users[i]+'">'+users[i]+"</option>");

            }

        });

다음은 위의 예제를 실행한 화면이다. 아래와 같이 TO 부분에서 사용자를 지정하고 메세지를 보내면 특정 사용자에게만 메세지가 전달됨을 확인할 수 있다.



다음에는 대화방의 기능을 추가하여, socket.io의 room 개념에 대해서 알아보도록 한다.



출처 : 조대협 (http://bcho.tistory.com)

'Programming > Node.js' 카테고리의 다른 글

Socket.IO 클러스터링  (0) 2014.05.08
Socket.IO 4/4 - 채팅방 기능 추가하기  (0) 2014.05.08
Socket.IO 2/4 API 요약  (0) 2014.05.08
Socket.IO (1/4)  (0) 2014.05.08
mySQL 연동  (0) 2014.05.08

Socket.IO APIs

Socket.IO 이밖에도 다양한 이벤트를 전달할  있는 API 제공하는데이에 대해서 살펴보자.

여기서 사용하는 socket이라는 객체는

io.sockets.on('connection',function(socket){

 의해서 callback function 의해서 전달된 인자임을 미리 명시해둔다.


1. 이벤트 보내기 받기

먼저 소켓으로 또는부터 이벤트를 보내고 받는 방법부터 알아보자.앞에 예제에서도 봤지만 가장 간단한 방법은

Ÿ  * 이벤트 보내기 socket.emit('이벤트명',{메세지});

현재 연결되어 있는 클라이언트 소켓에 “이벤트명”으로 “{메시지}” 데이터로 이벤트를 보낸다.

Ÿ  *  이벤트 받기 socket.on('이벤트명',function(data){ });

현재 연결되어 있는 클라이언트 소켓으로부터 들어오는 이벤트명이벤트에 대해서 두번째 인자로 정의된 callback function 의해서 이벤트에 대한 처리를 한다이때 이벤트 메시지는 callback function인자인 “data” 통해서 전달된다.

하나의 클라이언트가 아니라 다수의 다른 클라이언트나 또는 다른 클라이언트에 이벤트를 어떻게 보내는지알아보자

Ÿ  * 나를 제외한 다른 클라이언트들에게 이벤트 보내기 socket.broadcast.emit('이벤트명',{메세지});

socket 대해서 broadcast 하면나를 제외한 다른 소켓 클라이언트들에게 이벤트를 보낼  있다.

Ÿ  * 나를 포함한 모든 클라이언트들에게 이벤트 보내기io.sockets.emit('이벤트명',function(data){ });

개별 클라이언트 소켓을 대표하는 객체가 socket이라면전체 연결된 socket들을 대표하는 객체는io.sockets이다여기서는 io.sockets.emit 사용했는데이는 전체 연결된 클라이언트 소켓에 대해서이벤트를 보내도록  것이다.

 소켓이 아닌 다른 특정 소켓에게 이벤트를 보내는 방법이 있는데,

Ÿ  * io.sockets(socket_id).emit('이벤트명',function(data){ });

 사용하면 된다이때 socket_id socket.id 값으로  클라이언트 소켓은 id라는 property 가지고있고이는  소켓을 구별해주는 식별자가 된다그나중에 예제에서 설명하겠지만채팅 귓속말과 같이 특정 소켓으로 메시지를 보내려면메시지를 전달하는 대상이 되는 소켓의 id값을 알아서 위의io.socket(socket_id) 이벤트를 전달해야 한다.


2.  소켓에 데이터 바인딩

 소켓에는 소켓에 연관된 데이터를 set 메서드를 이용해서 binding하고, get 이용해서 binding  데이터를꺼낼  있다.

Ÿ   * socket.set(‘key’, ‘value’,function() {});

Ÿ   socket.get(‘key’function(err,value) {});

Ÿ   socket.del(‘key’function(err,value) {});

값으 저장할때는 set을 이용하여 socket key값을 키로 사용하여 value라는 데이터를 저장한다값을 읽어올 때는 get을 이용하여 socket에 저장된 key이름으로 저장된 값을 value를 통해서 리턴한다.그리고 해당값을 삭제하고자 할때는 del을 이용하여 socket key이름으로 저장된 값을 삭제한다.

socket도 객체이기 때문에 Object property를 사용해도 되는데예를 들어 socket.key = value 왜 굳이 set/get을 사용할까? socket.io의 set/get 내부 구현을 뜯어보면 실제로는 Object property를 사용한다 socket.iostore Redis로 지정하게 되면 set/get은 값을 내부 Object property에 저장하지 않고, Redis에 저장하게 되서이 값들은 클러스터 노드 (다른 노드간)에서도 접근이 가능해진다.

3.  Room 처리 (그룹)

socket.io 소켓들을 그룹핑하는 채널과 같은 개념인 ‘room’이라는 개념을 지원한다채팅 프로그램의 대화방과 같은 개념이다. Room 사용하게 되면 broadcast 하더라도 같은 room안에 있는 클라이언트에게만 이벤트가 전송된다.

Ÿ   socket.join(‘roon name’)

Ÿ   socket.leave(‘roon name’)

소켓을 특정 room binding하는 방법은 join 이용하면 해당 소켓은  room binding 되고, leave 하면 room에서부터 나오게 된다.

특정 room 있는 socket에게 이벤트를 보내는 것은 앞에 설명한 똑같이 socket.emit 사용하면 되는데, broadcast 하거나 room안에 있는 전체 클라이언트 소켓에게 이벤트를 보낼때는 아래와 같이 room 명시해주면 된다

Ÿ   io.sockets.in(‘roon name’).emit(‘event’,message)

‘room name’ room안에 있는 모든 클라이언트들에게 이벤트 보내기

Ÿ   socket.broadcast.to(‘roon name’).emit(‘event’,message)

 ‘room name’ room 안에 있는 나를 제외한 다른 클라이언트들에게 이벤트 보내기

또한 현재 생성되어 있는 room 대한 정보를 읽어오는 방법이 몇가지가 있는데,

Ÿ  io.sockets.manager.rooms

현재 생성되어 있는 모든 room 목록을 리턴한다.

Ÿ  io.sockets.clients(‘roon name’)

 ‘room name’ room 안에 있는 모든 클라이언트 소켓 목록을 리턴한다.

몇가지 주요 메서드들을 성명하였지만여기서 설명한 것은 일부에 불과하다상세한 내용들은 아래 내용을 참고하기바란다.

상세한 Configuration 처리 https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO

이벤트 종류(disconnect https://github.com/LearnBoost/socket.io/wiki/Exposed-events

자아 그러면 소개된 메서드들을 가지고앞에서 만든 채팅 프로그램의 기능을 더해보도록 하자



출처 : 조대협 (http://bcho.tistory.com)

'Programming > Node.js' 카테고리의 다른 글

Socket.IO 4/4 - 채팅방 기능 추가하기  (0) 2014.05.08
Socket.IO 3/4 (1:1 귓속말 구현)  (0) 2014.05.08
Socket.IO (1/4)  (0) 2014.05.08
mySQL 연동  (0) 2014.05.08
mongoose ODM 을 이용한 MongoDB 연동  (0) 2014.05.08

웹의 발전과 함께클라이언트의 요청에 대해서 응답만을 하는 단방향성이 아닌 양방향성의  사이트가 유행하게 되었는데, Socket.IO 자바스크립트 모듈로양방향 통신이 가능한 웹사이트를 구축하기 위해서 HTTP 클라이언트로 푸쉬 메시지를 보내줄  있는 모듈이다넓은 브라우져 지원성과 사용의 편의성 때문에 널리 사용되고 있고, node.js 인기 있어 지는 이유 중의 하나는 socket.io 때문이아닐까 한다.

배경

Socket.io를 설명하기 전에웹에서의 푸쉬 개념에 대해서 이해할 필요가 있다웹은 기반적으로 클라이언트에서 서버로 가는 단방향성이지만채팅과 같은 실시간 양방향 애플리케이나 쪽지와 같이 서버에서 클라이언트로 알림을 보내줘야 하는 요구 사항이 생겼다그래서 여러가지 기법이 생겨났는데자바스크립트 기반의 AJAX가 유행하면서 몇가지 기법이 생겨났는데그 내용을 살펴보면 다음과 같다.



웹 푸쉬 방식 비교 : Polling vs Long Polling vs Streaming

출처 : https://blogs.oracle.com/theaquarium/entry/slideshow_example_using_comet_dojo


Polling

가장 기본적인 기법으로클라이언트가 서버에 주기적으로 폴링(request를 보내는 기법)이다주기적으로 클라이언트가 자기가 처리해야할 이벤트가 있는지 없는지를 체크하는 것이다.

서버가 폴링 요청이 들어올때 마다 이를 처리해야 하고다음 폴링이 이루어지기 전까지는 어떤 이벤트가 오는지를 모르기 때문에결정적으로 실시간성이 보장이안된다.

예를 들어 폴링 주기가 10분이라고 할때 폴링 이후에 바로 이벤트가 들어왔을때다음 폴링주기 (10)을 기다려야 된다그리고 폴링 주기가 짧을 수 록 서버가 받는 부하가 크다예를 클라이언트가 작업할 내용이 있는지 확인하려면, DB드에 작업 내용을 저장해놓고폴링 때마다 체크해야 하는데이때 매번 DB 쿼리를 해야 한다면폴링 때마다 서버가 DB를 쿼리해야하기 때문에받아야 하는 트렌젝션이 매우 많고 서버의 부담이 기하 급수적으로 늘어난다따라서짧은 폴링 주기는 서버에 많은 부하를 주기 때문에적절하지 않으며 클라이언트로 보내는 푸쉬 메시지의 실시간성이 필요하지 않은 경우에 적절하며서버의 부하가 상대적으로 적고(폴링 주기가 길 경우기존의 웹백엔드 인프라 (Tomcat과 같은 미들웨어)를 그대로 활용할 수 있는 장점을 가지고 있다.


Long Polling

Long Polling Polling과 비슷하나 즉시성을 갖는다방식은 클라이언트가 HTTP request를 보내고바로 request를 닫는 것이 아니라일정 시간 동안(오랫동안열어 놓고 있다가 서버에서 클라이언트로 보내는 메시지가 있으면 메시지를 HTTP response로 실어 보내고해당Connection을 끊는다만약에 일정 시간동안 보낼 메시지가 없으면 HTTP 연결을 끊는다.

응답 메시지를 받건 안받건끊어진 연결은 다시 연결한다기본적으로 클라이언트가 연결을 해서 응답을 요청하는 Polling 형태이고응답이 오는지 기다리는 기간이 길기 때문에 이를 Long Polling 이라고 한다.

Long Polling의 경우 서버에 클라이언트들이 거의 항상 연결되어 있는 형태이기 때문에동시  서버의 동시에 연결할 수 있는 서버가 지원할 수 있는 동시 연결(Connection)수에 따라 결정된다.

예를 들어 Tomcat과 같은 WAS의 경우에는 HTTP 연결이 열려 있는 경우에는 1개의 Thread가 그 요청을 처리하기 위해서 사용되기 때문에, Tomcat Thread 100개인 경우, 1 Tomcat당 처리할 수 있는 Long Polling 가능한 클라이언트 수는 100개로 한정이 된다. (기존의 HTTP 요청을 처리하는 인프라로 핸들링하기 어렵다.)

서버로부터 푸쉬 메시지를 받으면 재 연결을 해야 하기 때문에클라이언트로 푸쉬하는 내용이 적을 경우에 유리하며 실시간 채팅과 같이 푸쉬해야 하는 메시지가 많은 경우에는 적절하지 않다. (채팅 메시지가 하나 왔다갔다 할 때 마다 재 연결을 해야 한다.)


Streaming

마지막으로 Streaming 기법인데이 기법은 일반적인 TCP Connection 처럼클라이언트가 서버로 연결을 맺은 후에그 연결을 통해서 서버가 이벤트를 보내는 방식이다. Long Polling이 이벤트를 받을 때마다 연결을 끊고 재 연결을 한가면, Streaming 방식은 한번 연결되면 계속해서 그 연결을 통해서 이벤트 메시지를 보내는 방식으로 재연결에 대한 부하가 없다.


WebSocket

이러한 푸쉬 로직을 AJAX 자바스크립트로 구현하다가 구현 방식이 브라우져들 마다 각기 상이하기 때문에 나온 표준이 WebSocket이라는 표준이다. http:// 대신 ws:// 로 시작하며 Streaming과 유사한 방식으로 푸쉬를 지원한다.

그러나 문제는 이 WebSocket 기술이 근래에 나왔기 때문에예전 브라우져는 지원하지 않는다는 것이다.



<그림웹소켓 지원 브라우져 현황>

출처 : http://caniuse.com

Socket.IO

Socket.IO  클라이언트로의 푸쉬를 지원하는 모듈인데 WebSocket 한계를 뛰어 넘어주는 모듈이다개발자는 Socket.IO 개발을 하고 클라이언트로 푸쉬 메시지를 보내기만 하면, WebSocket 지원하지 않는 브라우져의 경우브라우져 모델과 버전에 따라서 AJAX Long Polling, MultiPart Streaming, Iframe 이용한 푸쉬, JSONP Polling, Flash Socket  다양한 방법으로 내부적으로 푸쉬 메시지를 보내준다.

 WebSocket 지원하지 않는 어느 브라우져라도 푸쉬 메시지를 일관된 모듈로 보낼  있다.

간단한 예제를 살펴보자


간단한 채팅 프로그램

간단한 채팅 프로그램을 하나 살펴보자아래 프로그램은 브라우져에 접속하면 메시지를 입력 받을  있는 Input Box 띄워주고여기에 메시지를 입력하면 현재 연결되어 있는 모든 웹브라우져에 메시지를 보내주는 프로그램이다.

먼저 서버쪽 코드를 보자

/**

 * Module dependencies.

 */

 

var express = require('express');

var routes = require('./routes');

var http = require('http');

var path = require('path');

 

var app = express();

app.use(express.static(path.join(__dirname, 'public')));

 

var httpServer =http.createServer(app).listen(8080, function(req,res){

  console.log('Socket IO server has been started');

});

// upgrade http server to socket.io server

var io = require('socket.io').listen(httpServer);

 

io.sockets.on('connection',function(socket){

   socket.emit('toclient',{msg:'Welcome !'});

   socket.on('fromclient',function(data){

       socket.broadcast.emit('toclient',data); // 자신을 제외하고 다른 클라이언트에게 보냄

       socket.emit('toclient',data); // 해당 클라이언트에게만 보냄다른 클라이언트에 보낼려면?

       console.log('Message from client :'+data.msg);

   })

});

 

<코드. App.js>

Express에서 Socket IO 사용한 예제인데기존에 Express에서 사용한것과 같은 방식으로 httpServer 생성한다다음에httpServer socketIO 지원하는 서버로 다음과 같이 업그레이드를 한다.

var io = require('socket.io').listen(httpServer);

다음으로클라이언트가 socket.io 채널로 접속이 되었을때에 대한 이벤트를 정의한다.

io.sockets.on('connection',function(socket){

 같이 클라이언트가 접속이 되면, callback 수행하는데이때연결된 클라이언트의 socket 객체를 같이 넘긴다 socket 객체를받아서 코드에서는 연결된 클라이언트에게 “Welcome !”이라는 메시지를 보냈다.

socket.emit('toclient',{msg:'Welcome !'});

일반적인 이벤트 처리 방식과 같게해당 클라이언트 소켓에 emit 메서드를 이용하여이벤트를 전송하면 된다여기서는 “toclient”라는이벤트 명으로 msg라는 키를 갖고, value ‘Welcome !’ 이라는 값을 가지는 메시지를 전송하였다.

다음으로클라이언트로부터 오는 메시지를 처리하는 루틴인데채팅창에서 글을 쓰고 엔터를 누르면 서버로 “fromclient” 라는 이벤트를 보내도록 작성해놓았다그러면 서버쪽에서는 다음과 같이 socket.on(‘fromclient’ 라는 메서드를 이용하여 해당 이벤트에 따른 처리를 한다이때 들어오는 데이터는 채팅 문자열이 {msg:”문자열”} 형식으로 data라는 변수를 통해서 아래와 같이 들어오는데,

socket.on('fromclient',function(data){

채팅에서 이메세지를 다른 클라이언트들과 자신에게 다시 보낸다.

       socket.broadcast.emit('toclient',data);

       socket.emit('toclient',data);

socket.broadcast.emit 자신을 제외한 다른 모든 클라이언트에게 이벤트를 보내는 메서드이고, socket.emit 자신의 클라이언트()에게 이벤트를 보내는 메서드이다.

그러면 이제 클라이언트()쪽의 코드를 보자

<html>

<head>

 

    <title></title>

    <script src="/socket.io/socket.io.js"></script>

    <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>

 

</head>

<body>

    <b>Send message</b><p>

    Message  <input type="text" id="msgbox"/>

    <br>

    <span id="msgs"></span>

 

    <script type="text/javascript">

        var socket = io.connect('http://localhost');

        $("#msgbox").keyup(function(event) {

            if (event.which == 13) {

                socket.emit('fromclient',{msg:$('#msgbox').val()});

                $('#msgbox').val('');

            }

        });

        socket.on('toclient',function(data){

            console.log(data.msg);

            $('#msgs').append(data.msg+'<BR>');

        });

    </script>

</body>

</html>

<코드. index.html>

먼저 socket.io 사용하기 위해서 script src 아래와 같이 정의하고

<script src="/socket.io/socket.io.js"></script>

다음으로자바 스크립트가 실행되면, socket.io 서버로 연결을 한다.

var socket = io.connect('http://localhost');

그리고, input box에서 엔터를 누르면, input box 메시지를 읽어서, ‘fromclient’라는 이벤트를 서버에 전송한다.

socket.emit('fromclient',{msg:$('#msgbox').val()});

그리고 반대로서버로부터, ‘toclient’라는 이벤트가 들어오면들어온 문자열을 msgs라는 id 갖는 <span> 영역에 append 한다.

socket.on('toclient',function(data){

            console.log(data.msg);

            $('#msgs').append(data.msg+'<BR>');

클라이언트와 서버쪽 코드가  완성되었으면이를 배포하고 node.js 실행해서 테스트를 해보자.



<그림. socket.io 이용한 채팅 프로그램 화면>

다음에는 Socket.IO API들에 대한 소개와 1:1 귓속말, 그리고 그룹의 개념을 가지는 채팅방 예제에 대해서 설명하도록 한다.



출처 : 조대협 (http://bcho.tistory.com)

'Programming > Node.js' 카테고리의 다른 글

Socket.IO 3/4 (1:1 귓속말 구현)  (0) 2014.05.08
Socket.IO 2/4 API 요약  (0) 2014.05.08
mySQL 연동  (0) 2014.05.08
mongoose ODM 을 이용한 MongoDB 연동  (0) 2014.05.08
MongoDB 연동 (mongo-native)  (0) 2014.05.08

+ Recent posts