웹 소켓
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>