본문 바로가기

JAVA

JAVA 웹소켓 통신

1) 특징
web 환경에서 서버와 클라이언트 간에 메시지를 push방식으로 처리하는 것을 말한다.
일반적으로 웹 프로그래밍에서는 특정한 이벤트(submit)등에 의해 데이터를 서버에 
전달했지만, push방식으로 client가 요청하는 것이 아니라 서버에 의해서 적극적으로
client에 데이터를 전달하는 소켓통신을 이용한다

 

#웹 프로그래밍 서버 클라이언트 데이터 처리 방식
1. 페이지 호출과 요청값 전송
client ===페이지(컨트롤러) ==> server
<===해당 페이지/view==
client === 요청값(query string) ==> server

 

2. ajax처리
client === 요청값(query string) ==> server
client ===페이지(컨트롤러) ==> server
<===해당 json데이터 전달 ==

3.push 방식
client == 소켓통신(msg 전달) ==> server
server ==>소켓서버에 접속한 모든 칼리언트에게
메시지(push) ==> client

 

2) 주요 방식
client vs server
client는 웹 소켓 서버에 데이터를 능동적으로 전달할 뿐아니라, 수동적으로
서버에서 오는 데이터를 받을 수 있다. 주로 js에 의해 처리된다.
server는 client에 오는 데이터를 받아서, 이 서버와 소켙통신으로 연결된 client들에게
로직이나 조건에 의해 전부 또는 일부로 선택하여 데이터를 push방식으로 전송할 수 있다.

 

 

web.xml

<!--
7. 웹 소켓 통신
handler(java) <==> client(js) 
 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>  
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<mvc:default-servlet-handler/>
<!--  특정 url주소로 handler 객체를 호출 
/chat-ws.do 를 호출해서 서버에 handler 객체를 호출..
-->
<websocket:handlers>
<websocket:mapping handler="chatHandler" path="/chat-ws.do"/>
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/>
<!-- 로그인한 유저의 아이디를 알려면 http세션을 써야한다. 웹 소켓 세션에다가 http세션을 올려줘야 
접근이 가능하다. -->
</websocket:handshake-interceptors>
</websocket:handlers>

 

 

util

@Component("chatHandler")
public class ChattingHandler extends TextWebSocketHandler {

private Map<String, WebSocketSession> users = new ConcurrentHashMap();

//1.접속시
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 각 client를 추가 처리
users.put(session.getId(),session);
log(session.getId()+"님 접속합니다! 현재 접속자 수:"+users.size());
}

// 2.메시지 전송시
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
log(session.getId()+"에서 온 메시지:"+message.getPayload());

// 현재 접속한 모든 사람들에게 메시지 전송
for(WebSocketSession ws:users.values()) {
ws.sendMessage(message);
log(ws.getId()+"이게 전달한 메시지:"+message.getPayload());
}

}

// 3.접속 종료시
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// TODO Auto-generated method stub
//1. 등록된 사용자에서 제거 처리
users.remove(session.getId());
log(session.getId()+"접속 종료합니다.");
}

// 에러발생시
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
// TODO Auto-generated method stub
log(session.getId()+"에러 발생! 에러내용:"+exception.getMessage());
}

private void log(String msg) {
System.out.println("# 소켓 채팅 #"+ new Date()+":"+msg);
}

}

Controller

@Controller
public class ChattingController {

//http://localhost:7080/springweb/chattingFrm.do
@RequestMapping("chattingFrm.do")
public String chattingFrm() {
return "WEB-INF\\views\\a02_mvc\\a21_chatting.jsp";
}
}

 

 

jsp

<script type="text/javascript">
var wsocket;
$(document).ready(function(){
$("#enterBtn").click(function(){
if(confirm("채팅방 접속합니다.")){
conn();
}
});
// 아이디 입력 후,  enter 키를 입력시도 접속
$("#id").keyup(function(){
if(event.keyCode==13){
conn();
}
});
$("#exitBtn").click(function(){
if(confirm("접속을 종료하시겠습니까?")){
wsocket.send("msg:"+$("#id").val()+":접속 종료 했습니다.")
wsocket.close();
// 서버 handler public void afterConnectionClosed()
// 와 연동
}
});
});
function conn(){
wsocket = new WebSocket("ws:localhost:7080/${path}/chat-ws.do")
wsocket.onopen=function(evt){ // 접속하는 핸들러 메서드와 연결
console.log(evt)
// 능동적으로 서버에 소켓통신으로 메시지를 보내는 것..
wsocket.send("msg:"+$("#id").val()+":연결 접속했습니다.")
// "msg:himan:연결접속했습니다."
// msg:전송자:메시지명
// msg:그룹명:전송자:메시지 (단일 chatting/그룹 chatting)
}
// 메시지를 받을 때, 처리되는 메서드
// 서버에서 push방식으로 메시지를 전달 받는데..
//#참고
//1.webstorage 활용
//  1) 메시지 내용 임시 저장
// 2) 로그인한 id 임시 저장
wsocket.onmessage=function(evt){
var msg = evt.data
console.log(msg)
if(msg.substring(0,4)=="msg:"){
// msg:그룹명:전송자:메시지 (단일 chatting/그룹 chatting)
// 그룹에 해당할 때만 메시지를 받아서 처리하게 처리..


// msg: 를 제외한 모든 문자열을 추출
var revMsg = msg.substring(4)
console.log("#메시지 받기#")
console.log(msg)
$("#chatMessageArea").append(revMsg+"<br>")
// 자동 scolling 처리 로직
// 1.  전체 charMessageArea의 입력된 최대 높이 구하기
var mx = parseInt($("#chatMessageArea").height())
// 2. 포함하고 있는 div의 scollTop을 통해 최대한 내용으로 scrolling 하기
$("#chatArea").scrollTop(mx);
}
}
// 접속을 종료 처리할 때
wsocket.onclose=function(){
alert($("#id").val()+"접속 종료합니다.")
$("#chatMessageArea").val("")
$("#id").val("").focus();
}
}
</script>



<div class="jumbotron text-center">
  <h2>채팅화면</h2>

</div>
<div class="container">
<div class="input-group mb-2 ">
<div class="input-group-prepend ">
<span class="text-center input-group-text ">아이디</span>
</div>
<input id="id" class="form-control"  placeholder="접속할 아이디 입력하세요" />

<button type="button" id="enterBtn" class="btn btn-success">채팅입장</button>
<button type="button" id="exitBtn" class="btn btn-danger">나가기</button>
</div>  
 
<div class="input-group mb-2">
<div class="input-group-prepend">
<span class="text-center input-group-text">내 용</span>
</div>
<div id="chatArea" class="input-group-append">
<div id="chatMessageArea"></div>
</div>
</div> 

<div class="input-group mb-2">
<div class="input-group-prepend">
<span class="text-center input-group-text">메시지</span>
</div>
<input id="msg" class="form-control" 
 placeholder="보낼 메시지 입력" />
 
<button type="button" id="sndBtn"  class="btn btn-info">메시지전송</button>
</div> 
<script type="text/javascript">
$("#msg").keyup(function(){
if(event.keyCode==13){
wsocket.send("msg:"+$("#id").val()+":"+$(this).val())
$(this).val("").focus()
}
});
// 전송 버튼을 클릭시에 메시지 전송
$("#sndBtn").click(function(){
wsocket.send("msg:"+$("#id").val()+":"+$("#msg").val())
$("#msg").val("").focus()
});
</script>
</div>

 

'JAVA' 카테고리의 다른 글

JAVA fullcalendar 달력 캘린더 처리  (1) 2022.10.04
JAVA 다국어처리  (0) 2022.10.04
JAVA 메일전송  (0) 2022.10.04
JAVA 파일 업로드 다운로드  (0) 2022.10.04
JAVA 개발환경 설정  (1) 2022.08.25