JSP에서 실시간으로 통신을 사용할 때 소켓을 이용하게 된다.


미리 구현이 되어 있기 때문에 선언만 하고 메소드를 사용하게 된다.


기본 형태는 JSP에서 Jquery 형식으로 스크립트에 작성하게 된다.


JSP 스크립트 < - > 서블릿과 유사한 ServerEndPoint로


맵핑된 주소로 실시간으로 통신을 하게된다.





기본형태




// 먼저 페이지 시작 시 바로 getConnection 함수를 호출해 Server와 연결한다고 선언


$(function(){
     getConnection();

})



// getConnection이 호출 될 때 연결을 위해 사용하는 메소드들


function getConnection(){
     ws = new WebSocket("ws://localhost:8001" + '<%=request.getContextPath()%>/serverStart');


     // 서버 시작할 때 동작
     ws.onopen = function(event){

     }


     // 서버로부터 메세지를 전달 받을 때 동작하는 메소드

     // 아래에 선언 할 onMessage로 event가 전달된다.

     ws.onmessage = function(event){
           onMessage(event);
     }
               
     // 서버에서 에러가 발생할 경우 동작할 메소드
     ws.onerror = function(event){
          onError(event);
     }
               
     // 서버와의 연결이 종료될 경우 동작하는 메소드
     ws.onclose = function(event){
          onClose(event);
     }
}
           
           


// 전달할 String형 msg를 ws.send를 통해서 소켓으로 전달한다.

function send(msg){
     ws.send(msg);
}




// 서버에서 메시지를 전달 받을 때 event 매개변수로 값을 받고

// 이 메소드에서 event 값을 통해 무엇을 할 것인지 정한다.

function onMessage(event){


     // String 형태로 데이터가 넘어오므로 구분자를 통해서 사용하면 된다.


     // 구분을 "메세지:구분:아이디"와 같다고 할 때

     // 만약 event값이 "메세지내용:msg:3"과 같이 전달 되었다면

     // ":"를 split 메소드를 이용하여 분리하면 담긴 변수에는


     // serverMessage[0] = "메세지내용"

     // serverMessage[1] = "msg"

     // serverMessage[2] = "3"


     // 위와 같이 분리된다.


     // 아래의 예처럼 if문을 이용해서 잘 쓰면 된다.


     var serverMessage = event.data.split(":");


     if(serverMessage[1] ==  "msg") // msg, 메세지일 때

          alert(serverMessage[2] + "님의 메세지 : " + serverMessage[0]);

     } else if (serverMessage[1] == "alarm") {

          alert("알람이 있습니다."):

     }


    

}



// 소켓통신 에러 발생 시
function onError(event){
     alert(event.data);
}
// 소켓통신이 끝낫을 때
function onClose(event){
     alert(event);
}








body 부분에서는 예를들어 버튼에다가


<button onclick="send("안녕하세요:msg:3")"></button>


위와 같이 버튼이 있고 클릭하면 위에서 선언된 메소드인 send가 실행되어


ws.send()로 소켓을 통해 서버로 메세지가 전달이 된다.





다음은 서버에서 메세지를 받을때 파일의 예



코드를 보면 어노테이션을 통해 @ServerEndpoint("/auctionStart") 를 통해서 맵핑이 이루어져 있고


ws = ~~~~ 하고 위에서 Jquery로 선언한 부분에 주소가 맞으면


이 EndPoint를 통해서 통신을 하게 된다.







package com.kh.auction.websocket;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/auctionStart")
public class AuctionStart {
    private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>());

    @OnOpen
    public void onOpen(Session session) {
        //서버 연결한 시점에 동작하는 메소드
       
        //기존 사용자 리스트에 새로 연결 요청이 들어온 사용자를 추가한다
        clients.add(session);
    }

    @OnMessage
    public void onMessage(String msg, Session session) throws IOException {
        //서버로부터 데이터를 전송받을 경우 동작할 메소드
        System.out.println(msg);
       
        //하나의 일 처리를 수행하는동안 사용자의 변경이 일어나면 안된다.
        //즉 NullPointer를 방지하기 위해 동기화 처리를 해준다.
        synchronized(clients) {
            for(Session client : clients) {
                client.getBasicRemote().sendText(msg);
               
            }
        }
    }
   
    @OnError
    public void onError(Throwable e) {
        //데이터를 전달하는 과정에서 에러가 발생할 경우 동작하는 메소드
        e.printStackTrace();
    }
   
    @OnClose
    public void onClose(Session session) {
        //지워주지 않으면 Set에 이미 나간 사용자가 남아있기 때문에 메세지 전송시 에러 난다.
        clients.remove(session);
    }
   
   
   
}















private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>());


위의 선언을 통해서 현재 통신 시점의 모든 Session들의 정보를 담는다.


다른 부분은 건들일 일이 없는데 @OnMessage 이쪽 부분만 잘 사용하면 된다.


OnMessage 메소드를 통해서 전달된 String형 메세지가 이쪽으로 전달되고


데이터를 처리 한 후




synchronized(clients) {
            for(Session client : clients) {
                client.getBasicRemote().sendText(msg);
               
            }
}



synchronized 부분에서 아까 담았던 모든 session에게 해당 메세지를 전달한다.


client.getBasicRemote().sendText(msg); 이 부분을 수정하여


client의 값에서 id값과 같은 키값을 뽑아 조건문을 통해서


특정 대상만 구분하여 메세지를 보낼 수 있다.







synchronized 바로 윗 부분에서 msg 데이터를 마음대로 가공해도 되고 Service, Dao를 거쳐서


새로운 msg를 만들어도 된다.








결론



Endpoint 서버와 연결(이 때부터 소켓(ws)는 onMessage(event)를 계속 기다리고 있다.)


- ws.send를 통해 서버에 메세지 전달


- 서버에서 데이터 처리 후 세션에 데이터 전송


- 서버에서 메시지가 도착하면 onMessage(event)로 처리





메세지는 전부 String형으로 잘 컨트롤 해야 한다.


+ Recent posts