관리 메뉴

nalaolla

웹 소켓(spring을 이용한 채팅) 본문

SPRING

웹 소켓(spring을 이용한 채팅)

날아올라↗↗ 2016. 4. 26. 17:37
728x90
반응형

웹 소켓

Http protocol을 기반으로 하지만, WS라는 protocol을 쓴다.

웹 브라우저와 웹 서버 간의 양방향 통신을 지원하기 위한 표준이며,

클라이언트와 서버가 서로 실시간으로 메시지를 자유롭게 주고 받을 수 있다.

Windows Application 같은 어플리케이션의 개발이 가능하며, 주로 채팅 서비스를 개발한다.

 

JSR-356는 자바의 웹 소켓 표준이지만, 이것으로 서버 기능을 개발하기는 매우 힘들어서 spring이 지원을 해준다.

그게 WebSockHandler이다. JSR-356의 구현체로써 Spring에서 제공되고 있는 객체이다. Servlet 3의 웹 소켓 기능에 의존적이기 때문에 Servlet 3을 지원하지 않는 컨테이너에서는 사용 할 수 없다.

 

채팅을 할 수 있는 프로그램으로는 nodejs가 있으나, 사용하려면 서버가 독립적이기 때문에 느리며, Sing Thread이기 때문에 직렬지원을 하므로 여러명이 한꺼번에 이용한다면 문제가 발생한다.

반면, 웹 소켓은 직렬지원도 하며 또한, 병렬지원을 한다.


웹 소켓을 지원해주기 위한 설정

Maven의존 설정(poem.xml)

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>4.1.6.RELEASE</version>

</dependency>






EchoHandler.java


package com.ktds.mcjang.chat;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
 
public class EchoHandler extends TextWebSocketHandler{
    private static Logger logger = LoggerFactory.getLogger(EchoHandler.class);
    
    //방법일 일대일챗팅 map사용
    Map<String, WebSocketSession> sessions  = new HasMap<String, WebSocketSession>();*/
    
    private List<WebSocketSession> sessionList = new ArrayList<WebSocketSession>();
    /**
     * 클라이언트 연결 이후에 실행되는 메소드
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session)
            throws Exception {
        //Map사용시
        session.put(session.getId(), session);
        
        //List쓸때
        sessionList.add(session);
        logger.info("{} 연결됨", session.getId());
    }
    /**
     * 클라이언트가 웹소켓서버로 메시지를 전송했을 때 실행되는 메소드
     */
    @Override
    protected void handleTextMessage(WebSocketSession session,
        

        TextMessage message) throws Exception {

        logger.info("{}로 부터 {} 받음", session.getId(), message.getPayload());
        
        //배열이면 많이 쓸수 있고, 쓰지않으면 최대 2개임여
        /*logger.info("{}와 부터 {}받음",new String[] {session.getId(), message.getPayload()});*/
        
        //연결되어있는 모든 클라이언트들에게 메시지를 전송한다

        //session.sendMessage(new TextMessage("echo:" + message.getPayload()));

 

        for(WebSocketSession sess : sessionList){
            sess.sendMessage(new TextMessage("echo: " +  message.getPayload()));
        }
        
        /*map사용
        Interator<String> sessionIds = sessions.keySet().iterator();
        String sessionId="";
        while(sessionIds.hasNext()){s
            sessionId = sessionIds.next();
            sessions.get(sessionId).sendMessaget(new TextMessage("echo:" + message.getPayload()));
            
        }*/
        
    }
    /**
     * 클라이언트가 연결을 끊었을 때 실행되는 메소드
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session,
            CloseStatus status) throws Exception {
        //list
        sessionList.remove(session);
        //map
        //sessions.remove(session.getId());
        //logger.info("{} 연결 끊김", session.getId());
    }
    
    
}
 



web.xml에 추가할 부분  


<servlet>
      <servlet-name>dispatcherServlet</servlet-name>
      <servlet-class>
          org.springframework.web.servlet.DispatcherServlet
      </servlet-class>
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>
              /WEB-INF/config/spring/dispatcherServlet.xml
              /WEB-INF/config/spring/ws-config.xml
          </param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
  </servlet>




https://github.com/sockjs/sockjs-client





저장후 압축 푼 다음에





이파일을 첫번째 파일 위치를 봐서 옮김

<mvc:resources location="/WEB-INF/static/" mapping="/static/**"/> 




chat.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="<c:url value="/static/jquery/jquery-1.11.2.js"/>"></script>
<script type="text/javascript" src="<c:url value="/static/sockjs-0.3.4.js"/>"></script>
<script type="text/javascript">
    
    $(document).ready(function(){
        $("#sendBtn").click(function(){
            sendMessage();
        });
    });
    
    var sock;
    //웸소켓을 지정한 url로 연결한다.
    sock = new SockJS("<c:url value="/echo"/>");
    
    //자바스크립트 안에 function을 집어넣을 수 있음.
    //데이터가 나한테 전달되읐을 때 자동으로 실행되는 function
    sock.onmessage=onMessage;
    
    //데이터를 끊고싶을때 실행하는 메소드
    sock.onclose = onClose;
    
    /* sock.onopen = function(){
        sock.send($("#message").val());
    }; */
    function sendMessage(){
            /*소켓으로 보내겠다.  */
            sock.send($("#message").val());
    }
    //evt 파라미터는 웹소켓을 보내준 데이터다.(자동으로 들어옴)
    function onMessage(evt){
        var data = evt.data;
        $("#data").append(data+"<br/>");
        //sock.close();
    }
    
    function onClose(evt){
        $("#data").append("연결 끊김");
    }
    
</script>
</head>
<body>
<input type="text" id="message"/>
<input type="button" id="sendBtn" value="전송"/>
<div id="data"></div>
</body>
</html>


728x90
반응형