Http(Https) 프로토콜은 단반향이다.
⇒클라이언트 request(요청)에 서버가 response(응답) 하면 끝이다
근데 webSocket 양방향 통신, 프로토콜은 ws(wss)로 적는다.
최초에는 클라이언트가 연결 요청을 하지만, 일단 연결이 되면, 서버도 클라이언트에게 연락을 보낼수 있다
자바에서 웹소켓 덜 쓰는 이유 : node js가 실시간 앱에서 최적화 되어 있어서 채팅 알람등 실시간 관련 프로그램은 node로 많이 사용한다.
- pooling : 웹소켓 없을 때 사용한다. 클라이언트에 timer 줘서 주기적으로 한다.
- long pooling : 길게 timer준다.
웹소켓 설정
pom.xml
- pom.xml에 spring-websocket 라이브러리 추가한다.
<!-- spring-websocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework-version}</version>
</dependency>
websocket-context.xml
- 웹소켓 설정
- servlet-context.xml에 넣어도 되지만 보기가 안좋아서 websocket-context.xml 만들고 import 구문을 이용하여 넣어본다.
websocket.xml > Namespaces 클릭 > websocket 체크 클릭
<bean id="chatHandler" class="패키지명.ChatHandler" />
<websocket:handlers allowed-origins="*">
<websocket:mapping handler="chatHandler" path="/ws-chat" />
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor" />
</websocket:handshake-interceptors>
</websocket:handlers>
- HttpSessionHandshakeInterceptor : webSocketSession과 HttpSession 별도 존재해서 엔드포인트로 가기전에 중간에 인터셉트해서 HttpSession에 있는 값들을 WebSocketSession의 attribute로 넣어준다
servlet-context.xml
<beans:import resource="websocket-context.xml"/>
ChatHandler.java
package com.ddit.dditUniv.sample.handler;
import java.util.ArrayList;
import java.util.List;
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 ChatHandler extends TextWebSocketHandler {
private static List<WebSocketSession> list = new ArrayList<WebSocketSession>();
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
log.info("## 누군가 접속");
list.add(session);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String uMsg = message.getPayload();
log.debug("받은 텍스트 : {}",uMsg);
//서버도 사용자에게 메세지 보낼수 있음
TextMessage tmsg = new TextMessage("힘듬");
session.sendMessage(tmsg);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
log.info("## 누군가 떠남");
list.remove(session);
}
}
- JS으로 클라이언트 웹소켓 만들어야 접속 가능
- 웹소켓은 클라이언트끼리 대화 하는것이 아니다!!!!
- 웹소켓은 서버를 통해 대화(알람) 필요하다.
handleTextMessage 메소드
- 보낸 사람한테 tsmg ("힘듬") 통해 메세지 보낸다.
- js(jmchat.jsp) 에서 webSocket.onmessage 이벤트 발생된다.
ChatController.java
- jmchat.jsp 불러 줄 Controller를 1개 만들어준다
jmchat.jsp
- 클라이언트 웹소켓 코드를 가진 jmchat.jsp 만들어주자!
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>웹소켓 참 별거없어용</title>
</head>
<body>
<h1>웹소켓</h1>
<script>
//자동으로 접속시동
let webSocket = new WebSocket("ws://localhost/ws-chat");//클라이언트 웹소켓
//접속에 성공하면 자동으로 open 이벤트 발생 접속성공하면 뭘 할지 작성한다
webSocket.onopen = function(){
alert("헉 성공");
}
</script>
</body>
</html>
- websocket-context.xml 에서 ws-chat 으로 되어 있어서 url도 /ws-chat 써야된다.
서버를 자동으로 시작되므로 접속 시작되면 onoff 이벤트 발생된다
onopen ⇒ 접속 성공
성공하면 알람창으로 "헉 성공" 출력된다.
http://localhost/jm/chat
⇒ ChatController.java에서 요청한 url 접속해야 한다.
서버 접속이 성공하면 ChatHandler.java에서 afterConnectionEstablished 메소드 실행된다.
뒤로가기 클릭 하면 서버쪽 연결이 끊어진다.
webSocket.send() 이용해서 메세지 보낸다.
localhost 쓰면 다른 사람이 접속 못해서 IP 적어야한다.
localhost 자리에 IP 주소 넣었다
혼자 개발 할 때는 localhost 쓰고
다른 사람 채팅 할때 IP 주소 써야된다
url 부분 편하게 할려면
ip를 쓰면 ip를 , localhost를 쓰면 localhost가 들어 오도록 하고싶을때 아래 코드 사용한다.
let myServer = location.href.split("/")[2]; //http://localhost/ [2]가 서버명 도메인명들어온다
webSocket = new WebSocket(`ws://\${myServer}/ws-chat`); // End Point
원본
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>초우간단 채팅</title>
<style>
#id_chatwin {
width:300px;
height:300px;
background-color:black;
border:1px solid pink;
color:yellow;
}
</style>
</head>
<body>
<h1>간단히 억지롱 대화라도 할깡</h1>
<div>
<div id="id_chatwin"></div>
<input type="text" id="id_message" />
<input type="button" id="id_send" value="떤쏭">
<input type="button" id="id_exit" value="나갈령">
</div>
</body>
<script>
//그냥 띰띰해서 맹근 랜덤 아이디 맹그는 함쑹
const c_alpha="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const f_ranID=()=>{
let ranID ="";
for(let i=1; i< (Math.ceil(Math.random()*5)+4); i++){
ranID += c_alpha[Math.floor(Math.random()*c_alpha.length)];
}
return ranID;
}
let webSocket; // 페이지 바뀌면 변수가 사라진다는 사실에 주목할 필요가 있음
let myId = f_ranID();
const c_chatWin = document.querySelector("#id_chatwin");
const c_message = document.querySelector("#id_message");
const c_send = document.querySelector("#id_send");
const c_exit = document.querySelector("#id_exit");
c_send.addEventListener("click", ()=>{
send();
});
// 연결 끊깅
c_exit.addEventListener("click", function () {
disconnect();
});
//연결
connect();
function connect() {
//ip를 쓰면, ip가, localhost를 localhost가 들어오도록 하고픔
let myServer = location.href.split("/")[2]; //http://localhost/ [2]가 서버명 도메인명들어온다
webSocket = new WebSocket(`ws://\${myServer}/ws-chat`); // End Point
//이벤트에 이벤트핸들러 뜽록
webSocket.onopen = fOpen; // 소켓 접속되면 짜똥 실행할 함수(fOpen)
webSocket.onmessage = fMessage; // 써버에서 메쎄징 오면 짜똥 실행할 함수(fMessage)
}
//연결 시
function fOpen() {
webSocket.send(myId + "님 이프짱.");
}
function send() { // 써버로 메쎄찡 떤쏭하는 함수
let msg = c_message.value;
webSocket.send(myId + ":" + msg);
c_message.value = "";
}
function fMessage() {
let data = event.data;
c_chatWin.innerHTML = c_chatWin.innerHTML + "<br/>" + data;
}
function disconnect() { //써버와 인연 끊는 함쑹
webSocket.send(myId + "님이 뛰쳐나갔쪙");
webSocket.close();
}
</script>
</body>
</html>
여기서는 문자열 주고 받았는데, 실제로 프로그램 만들려면
JSON <-> 자바VO 변환을 위해서 Jackson 라이브러리의 ObjectMapper 클래스의 wirteValueAsString(자바VO) -> 자바VO를 JSON문자열로 변환
readValue(json문자열 변수, 자바VO.class) -> JSON문자열을 자바VO로 변환
메소드를 사용하고, 주고 받는 메세지의 필요한 속성들을 모아서 VO 클래스를 만들어 준다면,통신을 아주 편하게 할 수 있다
스프링부트 설정
@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private final ChatHandler chatHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(chatHandler, "/ws-chat").setAllowedOrigins("*")
.addInterceptors(new HttpSessionHandshakeInterceptor());
}
}
출처
https://e-7-e.tistory.com/42
'JAVA' 카테고리의 다른 글
JDK11 vs JDK 17 차이점 (0) | 2024.09.09 |
---|---|
Data 값 숫자로 변경된 경우 ex)1713925050000 수정 (0) | 2024.05.22 |
java Date 객체 이용한 당일 연월일 생성 (0) | 2024.05.11 |
SVN 설치 & 명령어 (0) | 2024.03.04 |
이클립스 export (내보내기),import(가져오기) (0) | 2024.02.17 |