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 |