[ Java / Socket ] JSON을 이용하여 소켓 통신 (비회원 채팅, 익명채팅)
2024. 6. 30. 15:27ㆍ· LANGUAGE/└ Java
환경 : Spring Tool Suite4
등록 → 재정의(Override) 순서로 socket을 활용하자~!!!!!1
- JsonWebSocketServer.java
/**
* 클라이언트와 JSON 형태의 데이터를 주고받도록 처리
* - 사용자가 보낸 메세지에 시간과 같은 정보를 추가하여 회신하도록 구현
* */
@Slf4j
@Service
public class JsonWebSocketServer extends TextWebSocketHandler{
private Set<WebSocketSession> users = new CopyOnWriteArraySet<>();//동기화 됨(자물쇠 있음)
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
users.add(session);
log.debug("사용자 접속! 현재 사용자 {}명", users.size());
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
users.remove(session);
log.debug("사용자 접속 종료! 현재 사용자 {}명", users.size());
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//서버와 클라이언트 간의 메세지 규약을 만들어보자
//- 클라이언트 -----> 서버 : ChatRequestVO
//- 서버 -----> 클라이언트 : ChatResponseVO
//[1] 사용자가 보낸 메세지를 ChatRequestVO로 해석
ObjectMapper mapper = new ObjectMapper();
ChatRequestVO requestVO = mapper.readValue(message.getPayload(), ChatRequestVO.class);
//[2] 사용자에게 보낼 메세지를 ChatResponseVO로 생성
ChatResponseVO responseVO = ChatResponseVO.builder()
.content(requestVO.getContent())//내용은 그대로 복사
.time(LocalDateTime.now().toString())//시간 추가
.build();
//[3] 메세지 객체 생성
String json = mapper.writeValueAsString(responseVO);
TextMessage response = new TextMessage(json);
//전체에게 메세지를 전송(broadcast)
for(WebSocketSession user : users) {
user.sendMessage(response);
}
}
}
- WebSocketServerConfiguration.java
/**
* 웹소켓과 관련된 설정을 작성하는 파일
* 이미 등록해둔 웹소켓 서버들을 가져와서 추가적인 설정을 한 뒤 활성화
* */
@EnableWebSocket//웹소켓을 사용할 것임을 표시(활성화)
@Configuration//설정파일임을 표시
public class WebSocketServerConfiguration implements WebSocketConfigurer {
@Autowired
private JsonWebSocketServer jsonWebSocketServer;
@Override
public void registerWebSocketHandlers (WebSocketHandlerRegistry registry) {
//SockJS를 사용하도록 설정하며 등록
//[1] 웹소켓을 지원하지 않는 브라우저는 유사기술로 웹소켓처럼 구현해줌
//(유사기술은 pulling, long-pulling과 같은 기술을 말함)
//[2] 주소를 http로 사용 가능하며, 아무나 들어오지 못하도록 ws 주소가 변함
//[3] 접속자에 대한 컴팩트한 관리가 가능하다(heartbeat 핑)
registry.addHandler(jsonWebSocketServer, "/ws/json")
.withSockJS();
}
}
서버와 클라이언트 간의 메세지 규약을 만들어보자
- 클라이언트 -----> 서버 : ChatRequestVO
- 서버 -----> 클라이언트 : ChatResponseVO
- ChatRequestVO.java
//클라이언트가 보내는 메세지
@JsonIgnoreProperties(ignoreUnknown = true)
@Data @Builder @NoArgsConstructor @AllArgsConstructor
public class ChatRequestVO {
private String content;//채팅내용
}
- ChatResponseVO.java
//클라이언트에게 보내는 메세지
@JsonIgnoreProperties(ignoreUnknown = true)
@Data @Builder @NoArgsConstructor @AllArgsConstructor
public class ChatResponseVO {
private String content;
private String time;
}
페이지 설정
- PageController.java
@Controller
@RequestMapping("/page")
public class PageController {
@RequestMapping("/json")
public String json() {
return "json";
}
}
- json.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- javascript toast library -->
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
<!-- sockjs cdn -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js"></script>
<!-- moment.js cdn -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/locale/ko.min.js"></script>
<h1>그룹채팅(JSON) 예제</h1>
<input type="text" class="text-input" placeholder="메세지 작성">
<button class="btn-send">전송</button>
<hr>
<div class="chat-wrapper"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
//시작하자마자 웹소켓 서버에 연결
window.socket = new SockJS("${pageContext.request.contextPath}/ws/json");
//연결 완료 시 해야할 작업들을 "콜백 함수"로 설정
window.socket.onmessage = function(e){
var obj = JSON.parse(e.data);//전송된 문자열을 객체로 변환
//obj는 ChatResponseVO와 동일한 구조를 가진다.
//시간 제어 라이브러리인 moment를 사용하여 시간 형식을 변경
//var time = moment(obj.time).fromNow();//현재시간 기준
//var time = moment(obj.time).format("HH:mm");//형식 지정
var time = moment(obj.time).format("a h:mm");//형식 지정
var area = $("<div>").append(obj.content)
.append("<br>")
.append(time);
$(".chat-wrapper").append(area);
}
//전송버튼을 누르면 입력한 메세지가 있는 경우 서버에 전송
$(".btn-send").click(function(){
var text = $(".text-input").val();//입력창의 입력값을 불러온다
if(text.length == 0) return;//입력값이 없으면 중지한다
//서버에서 이해할 수 있는 형태로 객체를 생성
var data = {
content: text
};
//byte아님 문자열만 전송 가능. 객체는 전송 불가
var json = JSON.stringify(data);//data를 JSON 문자열로 변환
window.socket.send(json);//서버로 입력값을 전송한다
$(".text-input").val("");//입력창의 입력값을 삭제한다
});
});
</script>
(+) 서버에서 byte 또는 문자열만 전송이 가능하다. 객체는 전송 불가능 하므로 data를 전송하고자 한다면 JSON 문자열로 변환하여 전송해야 한다.
(+) 해당 주소로 접속과 동시에 연결이 가능하도록 코드 구현
- 출력 결과
누가 작성했는지 모르지만, 외부에서 접속하여 작성할 수 있음
개인 공부 기록용입니다:)
728x90
'· LANGUAGE > └ Java' 카테고리의 다른 글
[ Java / Socket ] 통신 흐름 이해 (0) | 2024.06.30 |
---|---|
Heartbeat, Live Ping (0) | 2024.06.29 |
[ Java / Socket ] 접속자 제어 및 브로드캐스팅(그룹채팅 구현) (0) | 2024.06.29 |
[ Java / Socket ] 서버/클라이언트 통신 및 토스트 메세지 띄워보기 (0) | 2024.06.29 |
[ Java / Socket ] 웹 소켓 서버 생성 / 접속 / 접속종료 (0) | 2024.06.29 |