12/29 72-1 [SPRING] WebSocket
http는 클라이언트가요청을 해야 응답을 해주는 polling 방식임
요청이 없어도 응답을 해주는 push방식(실시간으로 데이터 주고받기)이
필요해서 나온게 요놈임
주기적으로 걍 계속 서버에 요청하는 것 보단 낫다고 함
프로토콜 형태는 ws://~~
서버부하, 보안(Security)적인 측면과 세션 관리 등의 문제를 가지고 있고
가장 큰 단점으로는 구 브라우저(IE 8.0)에서는 작동하지 않는 문제점이 있다
고는 하지만 요새 누가 구 버전을 쓰나
서버연결
=> WebSocket 객체를 통해 서버 연결
=>기본 포트 역시 http,https와 동일한 80,443을 이용
데이터 송신
=>end 함수로 데이터를 서버로 송신
데이터 수신
=>푸시(전송)하는 데이터를 받으려면 message 이벤트를 구현
채팅구현! 올 실제코드 가보자
항..... 수업시간에 적어놓은 메모장 다 날아가서 기억으로 더듬더듬 작성해야해.... 헝...그래도 뭔가 xml에 라이브러리 등록은 해야하니까 pom.xml에가서 라이브러리 등록 !
<!-- 웹 소켓용 라이브러리 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework-version}</version>
</dependency>
그리고 자바코드로 등록을 해야 겠지
WebSocketConfig.java
@Configuration
@EnableWebSocket //서블릿컨텍스트에다가 빈으로 설정한 것과 같음!!
public class WebSocketConfig implements WebSocketConfigurer{
//웹 소켓 서버를 생성자 인젝션으로 초기화 - 아래 ~메소드에서 사용해야해서..?
private final WebSocketServer webSocketServer;
public WebSocketConfig(WebSocketServer webSocketServer) {
this.webSocketServer=webSocketServer;
}
//클라이언트 접속을 위한 엔드포인트 설정
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketServer, "/chat-ws.do").setAllowedOrigins("*");
}
}
그리고 나서 웹소켓 서버를 설정 했던 것 같음
WebSocketServer.java
//웹 소켓 서버
@Component
public class WebSocketServer extends TextWebSocketHandler {
//접속한 클라이언트를 저장하기 위한 속성(멤버변수)
//키는 웹소켓 세션 아니디
private Map<String,WebSocketSession> clients = new HashMap<>();
//클라이언트와 연결 되었을 때 호출되는 콜백 메소드
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//컬렉션에 연결된 클라이언트 추가
clients.put(session.getId(), session);
System.out.println(session.getId()+"연결 되었습니다.");
}/////////
//클라이언트로부터 메시지를 받았을 때 호출되는 메소드
//여기서 클라이언트로 메시지도 보냄
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println(session.getId()+"로부터 받은 메시지"+message.getPayload());
//접속한 모든 클라이언트에게 session.getId()가 보낸 메시지 뿌리기
for(WebSocketSession client:clients.values()) {
if(!session.getId().equals(client.getId())) { //자기가 보낸 메시지를 자기한테 다시 받지 않도록
//받은 메시지를 그대로 접속한 모든 인원에게 push
client.sendMessage(message);
}
}
}///////////////
//통신 장애 시 자동으로 호출되는 메소드
@Override
public void handleTransportError(WebSocketSession session, Throwable e) throws Exception {
System.out.println(session.getId()+"와 통신장애 발생:"+e.getMessage());
}///////
//클라이언트와 연결 끊어졌을 때 호출되는 메소드
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
//컬렉션 저장 된 클라이언트 삭제
clients.remove(session.getId());
System.out.println(session.getId()+"연결이 끊어졌습니다.");
}/////////
}////////////////
근데 서버 잘 작동시키려면
방화벽 설정? 해줘야함
방화벽이 걍 다 막아버린댜
검색창에 방화벽 치면
요거 클릭
저거 다음 포트는 8080 넣어주
나머지는 쭉쭉
다음 누르다가 마지막
하면 서버설정 끝 !!!
그리고 뷰!!! 는 거의 가져오고
그 밑의 자바코드를 잘 보자!
//얜 그냥 뷰 .. 넘어가도 됨
<style>
p {
color: whitesmoke;
margin: 10px;
}
span {
display: inline-block;
max-width: 180px;
padding: 5px 10px;
position: relative;
word-wrap: break;
}
.ext {
text-align: left;
}
.ext span {
background: #000000;
border-radius: 0 5px 5px 5px;
}
.int {
text-align: right;
}
.int span {
background: #ff0000;
border-radius: 5px 5px 0 5px;
right: 0;
}
</style>
<div class="container">
<fieldset class=" form-group border p-3">
<legend class="w-auto px-3">웹소켓</legend>
<form>
<div class="form-group">
<label><kbd class="lead">닉네임</kbd></label>
<input type="text" class="form-control" id="nickname"
placeholder="닉네임을 입력하세요">
</div>
<input class="btn btn-info" type="button" id="enterBtn" value="입장">
<input class="btn btn-danger" type="button" id="exitBtn" value="퇴장">
<div class="form-group">
<h4>대화내용</h4>
<div id="chatArea">
<div id="chatMessage"
style="height: 300px; border: 1px gray solid; overflow:auto;"></div>
</div>
</div>
<div class="form-group">
<label><kbd class="lead">메시지</kbd></label>
<input type="text" class="form-control" id="message" placeholder="메시지를 입력하세요">
</div>
</form>
</fieldset>
</div>
<jsp:include page="/WEB-INF/views/template/Footer.jsp" />
요 밑에 진짜 중요한 스크립트 코드 !!!!!!!
채팅 테스트
localhost를 아이피로 변경(192.168.219.137 =>요건 내 아이피) 소스 및 브라우저 URL도 변경
그리고 인바운드 규칙추가 8080
채팅 말풍선
https://codepen.io/beumsk/pen/mmEzrE =>나중에 들어가 봐야지
<script>
//웹소켓 객체 저장용
var wsocket;
//닉 네임 저장용
var nickname;
//입장버튼 클릭 시 -서버와 연결된 웹소켓 클라이언트 생성
$('#enterBtn').one('click',function(){ //one 한 번만 입장해야 하니까
wsocket = new WebSocket("ws://192.168.219.137:8080<c:url value="/chat-ws.do"/>"); //wss 는 보안이 강화된것 얘는 443포트를 사용
console.log('wsocket:',wsocket);
//서버와 연결된 웹 소켓에 이벤트 등록(함수들은 밑으로 다 빼놓음)
wsocket.onopen = open; // open()들어가면 호출하는거여
wsocket.onclose=function(){
appendMessage("연결이 끊어 졌어요");
};
wsocket.onmessage=receive;
wsocket.onerror=function(e){
console.log('에러발생:',e)
}
});
//서버에 연결되었을 때 호출되는 콜백함수
function open(){
//서버로 연결한 사람의 정보(닉네임) 전송
//msg:kim가(이) 입장했어요 <---이건 걍 내맘대로 만드는 규칙임
//사용자가 입력한 닉네임 저장
nickname = $('#nickname').val();
wsocket.send('msg:'+nickname+'가(이) 입장했어요');
appendMessage("연결이 되었어요");
}
//서버에서 메시지를 받을 때마다 호출되는 함수
function receive(e){//e는 message이벤트 객체
//서버로부터 받은 데이타는 이벤트객체(e).data속성에 저장되어 있다
console.log('서버로부터받은 메시지:',e.data);
if(e.data.substring(0, 4) ==='msg:')
appendMessage("<p class='int'><span>"+e.data.substring(4)+"</span></p>");//서버로부터 받은 메시지를 msg:부분을 제외하고 div에 출력
}
function appendMessage(msg){ //이건 여러군데 사용해서 메소드로 뺀거
//$('#chatMessage').append(msg+"<br/>");
$('#chatMessage').append(msg);
$('#chatMessage').get(0).scrollTop = $('#chatMessage').get(0).scrollHeight;
//get(0)이거 자바스크립트로 바꾸는거였지...scrollTop랑 .scrollHeight는 스크롤바를계속 올리는 공식임
}
$('#message').on('keypress',function(e){
console.log('keypress이벤트 발생:',e.keyCode);
if(e.keyCode===13){//엔터 입력
//서버로 메시지 전송
wsocket.send('msg:'+nickname+'>>' +$(this).val());//msg:KOSMO>>안녕
//DIV(대화영역)에 메시지 출력
appendMessage("<p class='ext'><span>"+$(this).val()+"</span></p>");
//기존 메시지 클리어
$(this).val("");
//포커스 주기
$(this).focus();
$('#chatMessage').get(0).scrollTop = $('#chatMessage').get(0).scrollHeight;
}
})
//퇴장버튼 클릭 시
$('#exitBtn').one('click',function(){
wsocket.send('msg:'+nickname+'가(이) 퇴장했어요');
wsocket.close();
});
</script>
근데 코드분석은 좀 더 곱씹고 곱씹고 곱씹어야 겠다
눈에 안들어옴...