HTTP 프로토콜의 conectless구조에의해서 stateless특성이 생김. stateless를 극복하기 위한 scope.
이 구조를 극복하기위해 connectfull방식 이용함. (connection을 수립하고 끊을 때가 의도적으로 되게끔 한다.)
TCP 3-way Handshake
수시로 F5새로운 요청을 발생시켜야 커넥션을 연결할 수 있다. 이 문제를 해결하기위해 WEB SOCKET이 있다.
이 전의 방식이 있다. HTTP 1.0시절에는 웹소켓이 없었다. 그래서 인터벌 설정을 해놓고 일정한 주기로 서버에 연결을 수립하여 데이터를 갱신받았다. Long Polling구조 . 여러명이 하면 부하를 감당하기 힘들다. 그래서 web Socket으로 사용하여 커넥트풀방식을 사용하게 된다.
커넥트레스 : 의도적이지 않은 연결의 이음과 끊음
커넥트풀 : 의도적으로 연결하고 끊음.
https://socketsbay.com/test-websockets
WebSockets - 👩💻 Do tests for FREE 💪 - SocketsBay.com
SocketsBay.com: WebSockets - Do tests. 👨🏽Free test. 👍🏻 Flexibility - We can adjust to different situations. 🌇 Incredibly-fast websites. 🥇
socketsbay.com
연결이 끊이지 않았다. time 이 pending
wss 서버(시큐어서버)?
1. 클라이언트 사이드 자바스크립트 유아이 작성(이 사이트 주소 이용해서 그대로 해보자.)
<mvc:view-controller path="/websocket/sample1" view-name="websocket/sample1"/>
서블릿컨텍스트에 추가
<definition name="websocket/*" extends="parent">
<put-attribute name="body" value="/WEB-INF/jsp/websocket/{1}.jsp" />
</definition>
타일즈 설정파일에 추가
<security:intercept-url pattern="/websocket/**" access="permitAll"/>
시큐리티컨텍스트 추가
jsp 만들고실행
콘솔에 let ws = new WebSocket("wss://socketsbay.com/wss/v2/1/demo/") 웹소켓 객체 생성
웹소켓은 기본생성자가 없다. 웹소켓을 받을 서버가 필요함. 아까 그 주소의 서버를 넣어봄.
onopen 연결 잇기 핸들러
onclose 연결 끊기 핸들러
onerror 연결 오류
<script>
let ws = new WebSocket("wss://socketsbay.com/wss/v2/1/demo/");
ws.onopen=function(event){
console.log(event);
}
ws.onclose=function(event){
console.log(event);
}
ws.onmessage=function(event){
console.log(event);
}
}
</script>
event의 타겟은 웹소켓
에코사이트에서 보낸 메세지가 우리 어플리케이션에서 돌아간다.
이 데이타 프로퍼티가 내용을 담당.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h4> 웹소켓 샘플 </h4>
<button class="wsControl" data-role="connect">연결수립</button>
<button class="wsControl" data-role="disconnect" disabled="disabled">연결종료</button>
<div id = "messageArea">
</div>
<script>
const messageArea = $("#messageArea");
let ws = null;
const wsControl = $(".wsControl").on("click", function(event){
//html element의 데이터 속성 접근방법 dataset => map이다.
switch (this.dataset.role) {
case "connect":
ws = connectWS();
break;
default:
ws.close(1000); // 연결끊음. 정상종료시 종료코드 1000
break;
}
});
function connectWS(){
let ws = new WebSocket("wss://socketsbay.com/wss/v2/1/demo/");
ws.onopen=function(event){
console.log(event);
messageArea.append($("<p>").html("Connect!"));
// 문자열로 관리 attr, 값을 그대로 가지고 놀거다 prop
wsControl.prop("disabled", (i,v)=>!v); //!v로 disabled속성을 토글링할수있다.
}
ws.onclose=function(event){
console.log(event);
messageArea.append($("<p>").html("DisConnect!"));
wsControl.prop("disabled", (i,v)=>!v); //!v로 disabled속성을 토글링할수있다.
}
ws.onmessage=function(event){
console.log(event);
messageArea.append($("<p>").html(event.data));
}
return ws;
}
</script>
--------------------------------------
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework-version}</version>
</dependency>
추가
--------------------------------------
웹 소켓은 웹에 종속되어야하는 것. 그러니 하위컨테이너에 등록.
<param-value>
/WEB-INF/spring/servlet-context.xml
/WEB-INF/spring/websocket-context.xml
</param-value>
web.xml추가
public class SampleEchoWebSocketHandler extends TextWebSocketHandler
컨트롤러에서 TextWebSocketHandler이거를 상속받아.
<bean id="sampleEchoWebSocketHandler" class="kr.or.ddit.websocket.handler.SampleEchoWebSocketHandler"></bean>
<websocket:handlers>
<websocket:mapping handler="sampleEchoWebSocketHandler" path="/ws/echo"/>
</websocket:handlers>
빈으로 등록하고 상속받은 핸들러 등
2. 소켓 연결을 실제로 해줄 서버가 필요함
package kr.or.ddit.websocket.handler;
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;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SampleEchoWebSocketHandler extends TextWebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 클라이언트사이드로치면 onopen // super에서 하는일은 없음. // session 통로의미
log.info("연결 수립 : {}", session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// 클라이언트사이드로치면 onclose
log.info("연결 종료 : {}", session);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
// 클라이언트사이드로치면 onerror => exception이 하나 들어와있다.
log.error(exception.getMessage(), exception);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
// 클라이언트사이드로치면 onmessage => bainaryMessage는 파일도 전송가능하다.
String realMsg = message.getPayload();
session.sendMessage(new TextMessage(realMsg)); // session.sendMessage(message);
}
}
웹소켓은 형식이 없어서 sender에 대한 형식을 우리가 결정해주어야한다.