[Spring] websocket 사용하기(1)
client사이드와 server사이드 websocket 사용법이 존재함.
websocket의 단점.
message의 형식이 존재하지 않는다.
→ 어떤 형테로 데이터를 주고받을 지 모른다.
→ 단순한 문자열로 넘어간다.
이 단점을 보완하기 위해서 STOMP를 사용함.(여기서는 stomp는 사용하지 않음)
실제 사용할 때는 websocket + stomp를 사용해야 한다.
참조 : 사이트
https://www.websocket.org/echo.html
resposne line의 중요한 정보.
status code. (5가지 100, 200, 300, 400, 500번대)
실패 (400(client), 500(server))
성공 (200)
애매한성공 (300)
진행형 (100) - 웹소켓 연결 시 나옴.
wss 는 ssl인증서가 적용되어 있는 websocket프로토타입.(https와 동일)
connect 누른 후 개발자도구(f12)로 보기( network) status가 101로 표기된다.
disconnect 누르는 순간 Time이 Pending 에서 초로 바뀜,.
다시 connect를 클릭하면
이렇게 연결되어 있는 것을 알 수 있음.
*참고용 검색어 sockjs
wss://echo.websocket.org
client 사이드에서 만들기.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>websocket</title>
<jsp:include page="/includee/preScript.jsp"/>
</head>
<body>
<pre>
서버 : wss//echo.websocket.org
<input type="button" id = "connBtn" value="connect";/>
<input type="button" id = "disconnBtn" value="disconnect";/>
</pre>
<input type="text" id="msgArea"/>
<input type="button" id="sendBtn" value="메시지 전송" />
<div id="messages"></div>
<script type="text/javascript">
// 연결 부분만 바뀜. wss://localhost${cPath}/echo
var server = "wss//echo.websocket.org";
var ws = null;
$("#connBtn").on("click", function(){
ws = new WebSocket(server);
ws.onopen=function(event){
let serverURL = event.target.url;
console.log(serverURL+"와 연결수립");
}
ws.onerror=function(event){
console.log("에러 발생");
}
ws.onclose=function(event){
let serverURL = event.target.url;
console.log(serverURL+"연결 종료");
}
ws.onmessage=function(event){
let serverURL = event.target.url;
let receiveMsg = event.data;
console.log("메시지 수신"+receiveMsg);
let pTag = $("<p>").html("receive message : "+receiveMsg);
$("#messages").append(pTag);
}
});
$("#disconnBtn").on("click", function(){
if(ws==null) return;
ws.close();
});
$("#sendBtn").on("click", function(){
let message = $("#msgArea").val();
if(!message) return;
ws.send(message);
let pTag = $("<p>").html("send message : "+message);
$("#messages").append(pTag);
});
</script>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
서버 : wss//echo.websocket.org
코드블럭에서도, text로도 위와 같이 실행되서 사진으로 첨부함.
Spring-websocket 서버사이드에서 만들기.
웹소켓 구현히가 위한 dependency 3가지
pom.xml에서 추가 후 hirearchy에 잘 등록되어있는지 확인.
하위 컨테이너 - web에 종속된 녀석이기 때문에
Bean container를 새로 등록.
c - 생성자, p - getter, websocket을 클릭 한 후 생성하기.
서버사이드에 handler 생성하기
현재는 text만 보기 위해서 textWebSocketHandler를 상속받음.
package kr.or.ddit.websocket; import java.util.ArrayList; import java.util.List; import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Named; 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 WebsocketEchoHandler extends TextWebSocketHandler{ // @Inject // @Named("userList") @Resource(name = "userList") private List<WebSocketSession> userList; @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { userList.add(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { userList.remove(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 메시지 받기. 실제로 받은 데이터. payload는 짐덩이. String data = message.getPayload(); for(WebSocketSession user : userList) { user.sendMessage(new TextMessage(data)); } } }
message.getPayload()로 message 꺼내기.
등록된 각각의 user들에게 보내기 sendMessage가 TextMessage나 BinaryMessage를 보내야 한다고 함.
WebSocket message를 살펴보면
이렇게 여러개의 자식들이 존재하는 것을 알 수있음. 우린 이 중에서 text를 보내기 때문에 textMessage를 사용.
그래서 user.sendMessage(new TextMessage(data)); 작성.
handler를 bean에 등록하기. websocket의 경우 web에 종속되어 있기 때문에 하위 컨테이너에 생성.
위의 container를 bean에 등록한 후 불러주기 위해 web.xml에서 하나 더 추가하기.
serverside에서 회원 가입 시 현재 접속되어있는(userList에 추가되어있는) user들에게 실시간 알림을 보내주기 위해
상위 컨테이너(memberServiceImpl는 서버사이드기 때문에)에 userList 등록시키기.
WebsocketEchoHandler에서도 동일한 userList를 사용할 수 있게 하기 위해 inject해서 받아서 사용하기.
좀 더 명확하게 받아오기 위해서 @Resource로 name값 주기.
잘 작동함.