// Socket
- 네트워크상에서 호스트 간의 통신하는 규약(약속) - 인터페이스
- 여러 언어들이 Socket 구현 > 클래스 or 객체 제공
- 웹통신, Ajax 통신 > 단방향 통신(편지, 무전기)
<-> 소켓 통신 > 양방향 통신(전화)
// WebSocket
- HTML5 때 생성
- JavaScript에서 소켓 통신 지원
- Spring > WebSocket을 지원하는 API 제공
// 기본 설정 및 테스트
~ pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>websocket</artifactId>
<name>WebSocketTest</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>11</java-version>
<org.springframework-version>5.0.7.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet / JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<!-- WebSocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>11</source>
<target>11</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
~ web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
</web-app>
// 연결하기
~ "com.test.controller" > "SocketController.java"
package com.test.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class SocketController {
@GetMapping("/test.do")
public String test() {
return "test";
}
}
~ "com.test.server" > "SocketServer.java"
~ sevlet-context.xml > scan 하기
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.test.websocket" />
<context:component-scan base-package="com.test.controller" />
<context:component-scan base-package="com.test.server" />
</beans:beans>
~ views > "test.jsp"
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
</style>
</head>
<body>
<h1>WebSocket <small>연결 테스트</small></h1>
<div>
<button type="button" class="in" id="btnConnect">연결하기</button>
<button type="button" class="out" id="btnDisConnect">종료하기</button>
</div>
<hr>
<div>
<input type="text" class="long" id="msg">
<button type="button" class="add" id="btnEcho">에코 테스트</button>
</div>
<hr>
<div class="message full"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
//1. 소켓 생성
//2. 서버 접속(연결)
//3. 통신
//4. 서버 접속 종료
const uri = 'ws://localhost/websocket/server.do'
let ws;
$('#btnConnect').click(function() {
//1. 웹소켓 생성 > 자동으로 연결 요청
ws = new WebSocket(uri);
//웹소켓 서버에게 연결 요청이 성공하면 발생하는 이벤트 > 콜백 함수
ws.onopen = function(evt) {
log('서버와 연결되었습니다.');
};
ws.onclose = function(evt) {
log('서버와 종료되었습니다.');
}
ws.onmessage = function(evt) {
log(evt.data); //서버가 보낸 메시지
}
ws.onerror = function(evt) {
log('에러가 발생했습니다.')
}
});
$('#btnDisConnect').click(function() {
//연결된 소켓을 중단
ws.close();
log('연결을 종료합니다.');
});
$('#btnEcho').click(function() {
//연결된 소켓으로 서버에게 데이터 전송하기
//ws.CONNECTING : 연결중
//ws.OPEN : 열림 > 통신 가능 상태
//ws.CLOSING : 닫는중
//ws.CLOSED : 닫힘
if(ws.readyState == ws.OPEN) {
//ws.send('안녕하세요.');
ws.send($('#msg').val());
log('메시지를 전달했습니다.');
}
});
function log(msg) {
$('.message').prepend(`<div>[\${new Date().toLocaleTimeString()}] \${msg}</div>`);
}
</script>
</body>
</html>
// 알림 서비스
- 관리자가 접속자에게 공지 > 알림 표시 구현
~ com.test.controller > SocketController.java > admin(), user() 추가
package com.test.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class SocketController {
@GetMapping("/admin.do")
public String admin() {
return "admin";
}
@GetMapping("/user.do")
public String user() {
return "user";
}
}
~ com.test.server > "NoticeServer.java" > 메소드 선언
package com.test.server;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/noticeserver.do")
public class NoticeServer {
@OnOpen
public void handleOpen() {
}
@OnMessage
public void handleMessage() {
}
@OnClose
public void handleClose() {
}
@OnError
public void handleError(Throwable e) {
}
}
~ views > "admin.jsp" > ws.open 구현
~ com.test.server > NoticeServer.java > handleOpen 구현
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
</style>
</head>
<body>
<h1>알림 서비스<small>관리자</small></h1>
<div>
<textarea id="msg"></textarea>
<button type="button" id="btnSend" class="add">보내기</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
const uri = 'ws://localhost/websocket/noticeserver.do';
let ws;
$(document).ready(function() {//페이지 초기화
ws = new WebSocket(uri);
ws.onopen = function(evt) {
console.log('서버와 연결됨')
};
ws.onmessage = function(evt) { };
ws.onclose = function(evt) { };
ws.onerror = function(evt) { };
});
</script>
</body>
</html>
package com.test.server;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/noticeserver.do")
public class NoticeServer {
@OnOpen
public void handleOpen() {
System.out.println("연결 성공");
}
@OnMessage
public void handleMessage() {
}
@OnClose
public void handleClose() {
}
@OnError
public void handleError(Throwable e) {
}
}
~ views > admin.jsp > 메시지(버튼 클릭 이벤트) 구현
~ com.test.server > NoticeServer.java > handleMessgae 구현
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
</style>
</head>
<body>
<h1>알림 서비스<small>관리자</small></h1>
<div>
<textarea id="msg"></textarea>
<button type="button" id="btnSend" class="add">보내기</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
const uri = 'ws://localhost/websocket/noticeserver.do';
let ws;
$(document).ready(function() {//페이지 초기화
ws = new WebSocket(uri);
ws.onopen = function(evt) {
console.log('서버와 연결됨')
};
ws.onmessage = function(evt) { };
ws.onclose = function(evt) { };
ws.onerror = function(evt) { };
});
$('#btnSend').click(function() {
ws.send($('#msg').val());
});
</script>
</body>
</html>
package com.test.server;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/noticeserver.do")
public class NoticeServer {
@OnOpen
public void handleOpen(Session session) {
System.out.println("연결 성공");
}
@OnMessage
public void handleMessage(String msg, Session session) {
System.out.println("메시지: " + msg);
}
@OnClose
public void handleClose() {
}
@OnError
public void handleError(Throwable e) {
}
}
~ views > "user.jsp" > ready 구현
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
#msgBox {
border: 1px solid var(--border-color);
width: 250px;
height: 150px;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
background-color: #FFF;
border-radius: 5px;
position: fixed;
right: 20px;
bottom: -200px;
opacity: 0;
transition: all 1s;
}
</style>
</head>
<body>
<h1>알림 서비스 <small>유저</small></h1>
<div id="msgBox"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
const uri = "ws://localhost/websocket/noticeserver.do";
let ws;
$(document).ready(function() {
ws = new WebSocket(uri);
ws.onopen = function(evt) {
console.log('연결 성공');
};
ws.onmessage = function(evt) {
};
ws.onclose = function(evt) {
};
ws.onerror = function(evt) { };
});
</script>
</body>
</html>
~ com.test.server > NoticeServer.java > Session 연결
> sessionList 선언 및 handleOpen에서 활용
> handleMessage
package com.test.server;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/noticeserver.do")
public class NoticeServer {
private static List<Session> sessionList;
static {
sessionList = new ArrayList<Session>();
}
@OnOpen
public void handleOpen(Session session) {
System.out.println("연결 성공");
sessionList.add(session);
}
@OnMessage
public void handleMessage(String msg, Session session) {
System.out.println("메시지: " + msg);
//관리자 > (전송) > 공지사항 > (수신) > 서버 > (전송) > 모든 유저
for(Session s : sessionList) {
if(session != s) { //관리자 제외한 나머지 유저
try {
s.getBasicRemote().sendText(msg); //상대방의 소켓에 메세지 전송
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@OnClose
public void handleClose() {
}
@OnError
public void handleError(Throwable e) {
}
}
~ views > user.jsp > onmessage 메소드 구현
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
#msgBox {
border: 1px solid var(--border-color);
width: 250px;
height: 150px;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
background-color: #FFF;
border-radius: 5px;
position: fixed;
right: 20px;
bottom: -200px;
opacity: 0;
transition: all 1s;
}
</style>
</head>
<body>
<h1>알림 서비스 <small>유저</small></h1>
<div id="msgBox"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
const uri = "ws://localhost/websocket/noticeserver.do";
let ws;
$(document).ready(function() {
ws = new WebSocket(uri);
ws.onopen = function(evt) {
console.log('연결 성공');
};
ws.onmessage = function(evt) {
console.log(evt.data);
};
ws.onclose = function(evt) {
console.log('연결 종료');
};
ws.onerror = function(evt) { };
});
</script>
</body>
</html>
~ com.test.server > NoticeServer.java > clearSession 구현 + handleMessage에서 호출
package com.test.server;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/noticeserver.do")
public class NoticeServer {
private static List<Session> sessionList;
static {
sessionList = new ArrayList<Session>();
}
@OnOpen
public void handleOpen(Session session) {
System.out.println("연결 성공");
sessionList.add(session);
}
@OnMessage
public void handleMessage(String msg, Session session) {
clearSession();
System.out.println("메시지: " + msg);
//관리자 > (전송) > 공지사항 > (수신) > 서버 > (전송) > 모든 유저
for(Session s : sessionList) {
if(session != s) { //관리자 제외한 나머지 유저
try {
s.getBasicRemote().sendText(msg); //상대방의 소켓에 메세지 전송
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@OnClose
public void handleClose() {
}
@OnError
public void handleError(Throwable e) {
}
public void clearSession() {
Iterator<Session> iter = sessionList.iterator();
while(iter.hasNext()) {
if(!(iter.next()).isOpen()) {
iter.remove(); //접속이 끊긴 클라이언트 소켓(세션)을 제거
}
}
}
}
~ views > user.jsp > showMsgBox 수정 + ready(onmessage 호출)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
#msgBox {
border: 1px solid var(--border-color);
width: 250px;
height: 150px;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
background-color: #FFF;
border-radius: 5px;
position: fixed;
right: 20px;
bottom: -200px;
opacity: 0;
transition: all 1s;
}
</style>
</head>
<body>
<h1>알림 서비스 <small>유저</small></h1>
<div id="msgBox"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
function showMsgBox(msg) {
$('#msgBox').text(msg);
$('#msgBox').css({
bottom: '20px',
opacity: 1
});
setTimeout(function() {
$('#msgBox').css({
bottom: '-200px',
opacity: 0
});
}, 5000);
}
//showMsgBox();
const uri = "ws://localhost/websocket/noticeserver.do";
let ws;
$(document).ready(function() {
ws = new WebSocket(uri);
ws.onopen = function(evt) {
console.log('연결 성공');
};
ws.onmessage = function(evt) {
console.log(evt.data);
showMsgBox(evt.data);
};
ws.onclose = function(evt) {
console.log('연결 종료');
};
ws.onerror = function(evt) { };
});
</script>
</body>
</html>
// 채팅 서비스
~ com.test.controller > SocketController.java > chat() , index() 추가
package com.test.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class SocketController {
@GetMapping("/index.do")
public String index() {
return "index";
}
@GetMapping("/chat.do")
public String chat() {
return "chat";
}
}
~ views > "index.jsp" : 입장 페이지 > 화면 설계
> "chat.jsp" : 대화 페이지 > 화면 설계
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
</style>
</head>
<body>
<h1>WebSocket <small>Chat</small></h1>
<div>
<div class="group">
<label>대화명</label>
<input type="text" name="name" id="name" class="short">
</div>
</div>
<div>
<button type="button" class="in">들어가기</button>
<button type="button" class="in" data-name="강아지">강아지</button>
<button type="button" class="in" data-name="고양이">고양이</button>
<button type="button" class="in" data-name="토끼">토끼</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
</script>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<link rel="stylesheet" href="/websocket/resources/css/chat.css">
<style>
</style>
</head>
<body>
<div id="main">
<div id="header">
<h2>WebSocket <small></small></h2>
</div>
<div id="list">
</div>
<input type="text" id="msg" placeholder="대화 내용을 입력하세요.">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.11.8/dayjs.min.js"></script>
<script>
</script>
</body>
</html>
~ com.test.server > "ChatServer.java"
package com.test.server;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import com.google.gson.Gson;
import com.test.domain.ChatDTO;
@ServerEndpoint("/chatserver.do")
public class ChatServer {
private static List<Session> sessionList;
static {
sessionList = new ArrayList<Session>();
}
@OnOpen
public void handleOpen(Session session) {
System.out.println("연결 성공");
sessionList.add(session);
}
@OnMessage
public void handleMessage(String msg, Session session) {
}
@OnClose
public void handleClose() {
}
@OnError
public void handleError(Throwable e) {
}
}
~ views > index.jsp > 이미 열려있을 경우 새로고침 되지 않게 버튼 막아주기
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
</style>
</head>
<body>
<h1>WebSocket <small>Chat</small></h1>
<div>
<div class="group">
<label>대화명</label>
<input type="text" name="name" id="name" class="short">
</div>
</div>
<div>
<button type="button" class="in">들어가기</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
$('.in').click(function() {
let name = $(event.target).data('name');
if(name == null || name == undefined) {
name = $('#name').val();
}
let child = window.open('/websocket/chat.do', 'chat', 'width=404 height=510');
$('.in').css('opacity', .5);
$('.in').prop('disabled', true);
});
</script>
</body>
</html>
~ views > chat.jsp > 새로고침 막기 + 웹소켓 연결
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<link rel="stylesheet" href="/websocket/resources/css/chat.css">
<style>
</style>
</head>
<body>
<div id="main">
<div id="header">
<h2>WebSocket <small></small></h2>
</div>
<div id="list">
</div>
<input type="text" id="msg" placeholder="대화 내용을 입력하세요.">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.11.8/dayjs.min.js"></script>
<script>
window.onkeydown = function() {
if(event.keyCode == 116) {
event.preventDefault();
return false;
}
};
/*
101#hong#lee#안녕하세요.#2023... > 프로토콜 설계
서버 <- (대화) -> 클라이언트
- code: 상태코드
1. 새로운 유저가 들어옴
2. 기존 유저가 나감
3: 메시지 전달
4. 이모티콘 전달
- sender: 보내는 유저명
- receiver: 받는 유저명
- content: 멧지
- regdate: 날짜/시간
*/
const url = 'ws://localhost/websocket/chatserver.do';
let ws;
var name;
function connect(name) {
window.name = name;
$('#header small').text(name);
//연결하기
ws = new WebSocket(url);
ws.onopen = function(evt) {
log('서버 연결 성공');
};
}
function log(msg) {
console.log(`[\${new Date().toLocaleTimeString()}]` + msg);
}
</script>
</body>
</html>
~ views > index.jsp > child 채팅방 연결
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<style>
</style>
</head>
<body>
<h1>WebSocket <small>Chat</small></h1>
<div>
<div class="group">
<label>대화명</label>
<input type="text" name="name" id="name" class="short">
</div>
</div>
<div>
<button type="button" class="in">들어가기</button>
<button type="button" class="in" data-name="강아지">강아지</button>
<button type="button" class="in" data-name="고양이">고양이</button>
<button type="button" class="in" data-name="토끼">토끼</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
$('.in').click(function() {
let name = $(event.target).data('name');
if(name == null || name == undefined) {
name = $('#name').val();
}
let child = window.open('/websocket/chat.do', 'chat', 'width=404 height=510');
$('.in').css('opacity', .5);
$('.in').prop('disabled', true);
child.addEventListener('load', function() {
child.connect(name);
});
});
</script>
</body>
</html>
~ views > chat.jsp > onopen -> 내가 들어온 사실 알리기
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<link rel="stylesheet" href="/websocket/resources/css/chat.css">
<style>
</style>
</head>
<body>
<div id="main">
<div id="header">
<h2>WebSocket <small></small></h2>
</div>
<div id="list">
</div>
<input type="text" id="msg" placeholder="대화 내용을 입력하세요.">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.11.8/dayjs.min.js"></script>
<script>
window.onkeydown = function() {
if(event.keyCode == 116) {
event.preventDefault();
return false;
}
};
/*
101#hong#lee#안녕하세요.#2023... > 프로토콜 설계
서버 <- (대화) -> 클라이언트
- code: 상태코드
1. 새로운 유저가 들어옴
2. 기존 유저가 나감
3: 메시지 전달
4. 이모티콘 전달
- sender: 보내는 유저명
- receiver: 받는 유저명
- content: 멧지
- regdate: 날짜/시간
*/
const url = 'ws://localhost/websocket/chatserver.do';
let ws;
var name;
function connect(name) {
window.name = name;
$('#header small').text(name);
//연결하기
ws = new WebSocket(url);
ws.onopen = function(evt) {
log('서버 연결 성공');
//내가 접속했다고 다른 사람들에게 알리기
let chat = {
code: '1',
sender: window.name,
receiver: '',
content: '',
//JavaScript 날짜 시간 라이브러리(moment.js, day.js)
regdate: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
ws.send(JSON.stringify(chat));
print('', '입장했습니다.', 'me', 'state', chat.regdate);
$('#msg').focus();
};
ws.onmessage = function(evt) {
};
ws.onclose = function(evt) {
};
ws.onoerror = function(evt) {
};
}
function log(msg) {
console.log(`[\${new Date().toLocaleTimeString()}]` + msg);
}
</script>
</body>
</html>
~ "com.test.domain" > "ChatDTO.java"
package com.test.domain;
import lombok.Data;
@Data
public class ChatDTO {
private String code;
private String sender;
private String receiver;
private String content;
private String regdate;
}
~ com.test.server > ChatServer.java > handleMessage 구현
~ views > chat.jsp > 메시지 수신(onmessage)
package com.test.server;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import com.google.gson.Gson;
import com.test.domain.ChatDTO;
@ServerEndpoint("/chatserver.do")
public class ChatServer {
private static List<Session> sessionList;
static {
sessionList = new ArrayList<Session>();
}
@OnOpen
public void handleOpen(Session session) {
System.out.println("연결 성공");
sessionList.add(session);
}
@OnMessage
public void handleMessage(String msg, Session session) {
System.out.println(msg);
//JSON <- (변환) -> Java Object
// - GSON
Gson gson = new Gson();
ChatDTO dto = gson.fromJson(msg, ChatDTO.class);
if (dto.getCode().equals("1")) {
//새로운 유저가 접속했습니다. > 모든 사람에게 알림 (현재 접속자 제외)
for(Session s : sessionList) {
if(s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
@OnClose
public void handleClose() {
}
@OnError
public void handleError(Throwable e) {
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<link rel="stylesheet" href="/websocket/resources/css/chat.css">
<style>
</style>
</head>
<body>
<div id="main">
<div id="header">
<h2>WebSocket <small></small></h2>
</div>
<div id="list">
</div>
<input type="text" id="msg" placeholder="대화 내용을 입력하세요.">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.11.8/dayjs.min.js"></script>
<script>
window.onkeydown = function() {
if(event.keyCode == 116) {
event.preventDefault();
return false;
}
};
/*
101#hong#lee#안녕하세요.#2023... > 프로토콜 설계
서버 <- (대화) -> 클라이언트
- code: 상태코드
1. 새로운 유저가 들어옴
2. 기존 유저가 나감
3: 메시지 전달
4. 이모티콘 전달
- sender: 보내는 유저명
- receiver: 받는 유저명
- content: 멧지
- regdate: 날짜/시간
*/
const url = 'ws://localhost/websocket/chatserver.do';
let ws;
var name;
function connect(name) {
window.name = name;
$('#header small').text(name);
//연결하기
ws = new WebSocket(url);
ws.onopen = function(evt) {
log('서버 연결 성공');
//내가 접속했다고 다른 사람들에게 알리기
let chat = {
code: '1',
sender: window.name,
receiver: '',
content: '',
//JavaScript 날짜 시간 라이브러리(moment.js, day.js)
regdate: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
ws.send(JSON.stringify(chat));
print('', '입장했습니다.', 'me', 'state', chat.regdate);
$('#msg').focus();
};
ws.onmessage = function(evt) {
log('메시지 수신')
let chat = JSON.parse(evt.data);
log(chat.code + ':' + chat.sender);
if(chat.code == '1') {
//다른 사람 입장
print('', `[\${chat.sender}]님이 입장했습니다.`, 'other', 'state', chat.regdate);
}
};
ws.onclose = function(evt) {
};
ws.onoerror = function(evt) {
};
}
function log(msg) {
console.log(`[\${new Date().toLocaleTimeString()}]` + msg);
}
</script>
</body>
</html>
~ com.test.server > ChatServer.java > else if (dto.getCode().equals("2")) {} 구현
~ views > chat.jsp > 메시지 수신(onmessage)
package com.test.server;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import com.google.gson.Gson;
import com.test.domain.ChatDTO;
@ServerEndpoint("/chatserver.do")
public class ChatServer {
private static List<Session> sessionList;
static {
sessionList = new ArrayList<Session>();
}
@OnOpen
public void handleOpen(Session session) {
System.out.println("연결 성공");
sessionList.add(session);
}
@OnMessage
public void handleMessage(String msg, Session session) {
System.out.println(msg);
//JSON <- (변환) -> Java Object
// - GSON
Gson gson = new Gson();
ChatDTO dto = gson.fromJson(msg, ChatDTO.class);
if (dto.getCode().equals("1")) {
//새로운 유저가 접속했습니다. > 모든 사람에게 알림 (현재 접속자 제외)
for(Session s : sessionList) {
if(s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (dto.getCode().equals("2")) {
//누군가가 퇴장 > 나머지 사람들에게 알려줌
sessionList.remove(session); //서버 측에서의 퇴장
for(Session s : sessionList) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@OnClose
public void handleClose() {
}
@OnError
public void handleError(Throwable e) {
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<link rel="stylesheet" href="/websocket/resources/css/chat.css">
<style>
</style>
</head>
<body>
<div id="main">
<div id="header">
<h2>WebSocket <small></small></h2>
</div>
<div id="list">
</div>
<input type="text" id="msg" placeholder="대화 내용을 입력하세요.">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.11.8/dayjs.min.js"></script>
<script>
$(window).on('beforeunload', function() {
$(opener.document).find('.in').css('opacity', 1);
$(opener.document).find('.in').prop('disabled', false);
//내가 나간다고 서버에게 메시지 보내기
let chat = {
code: '2',
sender: window.name,
receiver: '',
content: '',
//JavaScript 날짜 시간 라이브러리(moment.js, day.js)
regdate: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
ws.send(JSON.stringify(chat));
});
window.onkeydown = function() {
if(event.keyCode == 116) {
event.preventDefault();
return false;
}
};
/*
101#hong#lee#안녕하세요.#2023... > 프로토콜 설계
서버 <- (대화) -> 클라이언트
- code: 상태코드
1. 새로운 유저가 들어옴
2. 기존 유저가 나감
3: 메시지 전달
4. 이모티콘 전달
- sender: 보내는 유저명
- receiver: 받는 유저명
- content: 멧지
- regdate: 날짜/시간
*/
const url = 'ws://localhost/websocket/chatserver.do';
let ws;
var name;
function connect(name) {
window.name = name;
$('#header small').text(name);
//연결하기
ws = new WebSocket(url);
ws.onopen = function(evt) {
log('서버 연결 성공');
//내가 접속했다고 다른 사람들에게 알리기
let chat = {
code: '1',
sender: window.name,
receiver: '',
content: '',
//JavaScript 날짜 시간 라이브러리(moment.js, day.js)
regdate: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
ws.send(JSON.stringify(chat));
print('', '입장했습니다.', 'me', 'state', chat.regdate);
$('#msg').focus();
};
ws.onmessage = function(evt) {
log('메시지 수신')
let chat = JSON.parse(evt.data);
log(chat.code + ':' + chat.sender);
if(chat.code == '1') {
//다른 사람 입장
print('', `[\${chat.sender}]님이 입장했습니다.`, 'other', 'state', chat.regdate);
} else if (chat.code == '2') {
//다른 사람 퇴장
print('', `[\${chat.sender}]님이 퇴장했습니다.`, 'other', 'state', chat.regdate);
}
};
ws.onclose = function(evt) {
};
ws.onoerror = function(evt) {
};
}
function log(msg) {
console.log(`[\${new Date().toLocaleTimeString()}]` + msg);
}
</script>
</body>
</html>
~ views > chat.jsp > 엔터 입력해서 메시지 전송하기
~ com.test.server > ChatServer.java > else if (dto.getCode().equals("3")) {} 구현
~ views > chat.jsp > 수신한 내용 출력
package com.test.server;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import com.google.gson.Gson;
import com.test.domain.ChatDTO;
@ServerEndpoint("/chatserver.do")
public class ChatServer {
private static List<Session> sessionList;
static {
sessionList = new ArrayList<Session>();
}
@OnOpen
public void handleOpen(Session session) {
System.out.println("연결 성공");
sessionList.add(session);
}
@OnMessage
public void handleMessage(String msg, Session session) {
System.out.println(msg);
//JSON <- (변환) -> Java Object
// - GSON
Gson gson = new Gson();
ChatDTO dto = gson.fromJson(msg, ChatDTO.class);
if (dto.getCode().equals("1")) {
//새로운 유저가 접속했습니다. > 모든 사람에게 알림 (현재 접속자 제외)
for(Session s : sessionList) {
if(s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (dto.getCode().equals("2")) {
//누군가가 퇴장 > 나머지 사람들에게 알려줌
sessionList.remove(session); //서버 측에서의 퇴장
for(Session s : sessionList) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (dto.getCode().equals("3")) {
//대화 메시지를 모두에게 전달
for (Session s : sessionList) {
if(s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
@OnClose
public void handleClose() {
}
@OnError
public void handleError(Throwable e) {
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<link rel="stylesheet" href="/websocket/resources/css/chat.css">
<style>
</style>
</head>
<body>
<div id="main">
<div id="header">
<h2>WebSocket <small></small></h2>
</div>
<div id="list">
</div>
<input type="text" id="msg" placeholder="대화 내용을 입력하세요.">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.11.8/dayjs.min.js"></script>
<script>
$(window).on('beforeunload', function() {
$(opener.document).find('.in').css('opacity', 1);
$(opener.document).find('.in').prop('disabled', false);
//내가 나간다고 서버에게 메시지 보내기
let chat = {
code: '2',
sender: window.name,
receiver: '',
content: '',
//JavaScript 날짜 시간 라이브러리(moment.js, day.js)
regdate: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
ws.send(JSON.stringify(chat));
});
window.onkeydown = function() {
if(event.keyCode == 116) {
event.preventDefault();
return false;
}
};
/*
101#hong#lee#안녕하세요.#2023... > 프로토콜 설계
서버 <- (대화) -> 클라이언트
- code: 상태코드
1. 새로운 유저가 들어옴
2. 기존 유저가 나감
3: 메시지 전달
4. 이모티콘 전달
- sender: 보내는 유저명
- receiver: 받는 유저명
- content: 멧지
- regdate: 날짜/시간
*/
const url = 'ws://localhost/websocket/chatserver.do';
let ws;
var name;
function connect(name) {
window.name = name;
$('#header small').text(name);
//연결하기
ws = new WebSocket(url);
ws.onopen = function(evt) {
log('서버 연결 성공');
//내가 접속했다고 다른 사람들에게 알리기
let chat = {
code: '1',
sender: window.name,
receiver: '',
content: '',
//JavaScript 날짜 시간 라이브러리(moment.js, day.js)
regdate: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
ws.send(JSON.stringify(chat));
print('', '입장했습니다.', 'me', 'state', chat.regdate);
$('#msg').focus();
};
ws.onmessage = function(evt) {
log('메시지 수신')
let chat = JSON.parse(evt.data);
log(chat.code + ':' + chat.sender);
if(chat.code == '1') {
//다른 사람 입장
print('', `[\${chat.sender}]님이 입장했습니다.`, 'other', 'state', chat.regdate);
} else if (chat.code == '2') {
//다른 사람 퇴장
print('', `[\${chat.sender}]님이 퇴장했습니다.`, 'other', 'state', chat.regdate);
} else if (chat.code == '3') {
//대화 수신
print(chat.sender, chat.content, 'other', 'msg', chat.regdate);
}
};
ws.onclose = function(evt) {
};
ws.onoerror = function(evt) {
};
}
function log(msg) {
console.log(`[\${new Date().toLocaleTimeString()}]` + msg);
}
function print(name, msg, side, state, time) {
let temp = `
<div class="item \${state} \${side}">
<div>
<div>\${name}</div>
<div>\${msg}</div>
</div>
<div>\${time}</div>
</div>
`;
$('#list').append(temp);
scrollList();
}
$('#msg').keydown(function(evt) {
if(evt.keyCode == 13) {
let chat = {
code: '3',
sender: window.name,
receiver: '',
content: $('#msg').val(),
//JavaScript 날짜 시간 라이브러리(moment.js, day.js)
regdate: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
ws.send(JSON.stringify(chat));
if(chat.code == '3') {
print(window.name, chat.content, 'me','msg', chat.regdate);
}
$('#msg').val('').focus();
}
});
function scrollList() {
$('#list').scrollTop($('#list')[0].scrollHeight + 500);
}
</script>
</body>
</html>
~ views > chat.jsp > 이모티콘 전송
~ com.test.server > ChatServer.java > else if (dto.getCode().equals("4")) {} 구현
~ views > chat.jsp > printImoticon() 구현
package com.test.server;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import com.google.gson.Gson;
import com.test.domain.ChatDTO;
@ServerEndpoint("/chatserver.do")
public class ChatServer {
private static List<Session> sessionList;
static {
sessionList = new ArrayList<Session>();
}
@OnOpen
public void handleOpen(Session session) {
System.out.println("연결 성공");
sessionList.add(session);
}
@OnMessage
public void handleMessage(String msg, Session session) {
System.out.println(msg);
//JSON <- (변환) -> Java Object
// - GSON
Gson gson = new Gson();
ChatDTO dto = gson.fromJson(msg, ChatDTO.class);
if (dto.getCode().equals("1")) {
//새로운 유저가 접속했습니다. > 모든 사람에게 알림 (현재 접속자 제외)
for(Session s : sessionList) {
if(s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (dto.getCode().equals("2")) {
//누군가가 퇴장 > 나머지 사람들에게 알려줌
sessionList.remove(session); //서버 측에서의 퇴장
for(Session s : sessionList) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (dto.getCode().equals("3")) {
//대화 메시지를 모두에게 전달
for (Session s : sessionList) {
if(s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (dto.getCode().equals("4")) {
//이모티콘 메시지를 모두에게 전달
for (Session s : sessionList) {
if(s != session) {
try {
s.getBasicRemote().sendText(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
@OnClose
public void handleClose() {
}
@OnError
public void handleError(Throwable e) {
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
<link rel="stylesheet" href="/websocket/resources/css/chat.css">
<style>
</style>
</head>
<body>
<div id="main">
<div id="header">
<h2>WebSocket <small></small></h2>
</div>
<div id="list">
</div>
<input type="text" id="msg" placeholder="대화 내용을 입력하세요.">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.11.8/dayjs.min.js"></script>
<script>
$(window).on('beforeunload', function() {
$(opener.document).find('.in').css('opacity', 1);
$(opener.document).find('.in').prop('disabled', false);
//내가 나간다고 서버에게 메시지 보내기
let chat = {
code: '2',
sender: window.name,
receiver: '',
content: '',
//JavaScript 날짜 시간 라이브러리(moment.js, day.js)
regdate: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
ws.send(JSON.stringify(chat));
});
window.onkeydown = function() {
if(event.keyCode == 116) {
event.preventDefault();
return false;
}
};
/*
101#hong#lee#안녕하세요.#2023... > 프로토콜 설계
서버 <- (대화) -> 클라이언트
- code: 상태코드
1. 새로운 유저가 들어옴
2. 기존 유저가 나감
3: 메시지 전달
4. 이모티콘 전달
- sender: 보내는 유저명
- receiver: 받는 유저명
- content: 멧지
- regdate: 날짜/시간
*/
const url = 'ws://localhost/websocket/chatserver.do';
let ws;
var name;
function connect(name) {
window.name = name;
$('#header small').text(name);
//연결하기
ws = new WebSocket(url);
ws.onopen = function(evt) {
log('서버 연결 성공');
//내가 접속했다고 다른 사람들에게 알리기
let chat = {
code: '1',
sender: window.name,
receiver: '',
content: '',
//JavaScript 날짜 시간 라이브러리(moment.js, day.js)
regdate: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
ws.send(JSON.stringify(chat));
print('', '입장했습니다.', 'me', 'state', chat.regdate);
$('#msg').focus();
};
ws.onmessage = function(evt) {
log('메시지 수신')
let chat = JSON.parse(evt.data);
log(chat.code + ':' + chat.sender);
if(chat.code == '1') {
//다른 사람 입장
print('', `[\${chat.sender}]님이 입장했습니다.`, 'other', 'state', chat.regdate);
} else if (chat.code == '2') {
//다른 사람 퇴장
print('', `[\${chat.sender}]님이 퇴장했습니다.`, 'other', 'state', chat.regdate);
} else if (chat.code == '3') {
//대화 수신
print(chat.sender, chat.content, 'other', 'msg', chat.regdate);
} else if (chat.code == '4') {
//이모티콘 수신
printEmoticon(chat.sender, chat.content, 'other', 'msg', chat.regdate);
}
};
ws.onclose = function(evt) {
};
ws.onoerror = function(evt) {
};
}
function log(msg) {
console.log(`[\${new Date().toLocaleTimeString()}]` + msg);
}
function print(name, msg, side, state, time) {
let temp = `
<div class="item \${state} \${side}">
<div>
<div>\${name}</div>
<div>\${msg}</div>
</div>
<div>\${time}</div>
</div>
`;
$('#list').append(temp);
scrollList();
}
function printEmoticon(name, msg, side, state, time) {
let temp = `
<div class="item \${state} \${side}">
<div>
<div>\${name}</div>
<div style="background-color:#FFF;border:0;"><img src="/websocket/resources/emoticon/\${msg}.png"></div>
</div>
<div>\${time}</div>
</div>
`;
$('#list').append(temp);
setTimeout(scrollList, 100);
}
$('#msg').keydown(function(evt) {
if(evt.keyCode == 13) {
let chat = {
code: '3',
sender: window.name,
receiver: '',
content: $('#msg').val(),
//JavaScript 날짜 시간 라이브러리(moment.js, day.js)
regdate: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
//이모티콘 전송
if($('#msg').val().startsWith('/')) {
chat.code = '4';
chat.content = chat.content.split(' ')[0];
}
ws.send(JSON.stringify(chat));
if(chat.code == '3') {
print(window.name, chat.content, 'me','msg', chat.regdate);
} else if (chat.code == '4') {
printEmoticon(window.name, chat.content, 'me','msg', chat.regdate);
}
$('#msg').val('').focus();
}
});
function scrollList() {
$('#list').scrollTop($('#list')[0].scrollHeight + 500);
}
</script>
</body>
</html>
'서버 > Spring' 카테고리의 다른 글
[스프링(Spring)] RESTful (0) | 2023.06.22 |
---|---|
[Spring Security] 권한 체크 (0) | 2023.06.22 |
[Spring Security] 회원가입, 자동 로그인 (0) | 2023.06.22 |
[Spring Security] 로그인, 로그아웃, 계정 정보 (0) | 2023.06.21 |
[스프링(Spring)] 파일 업로드 / 다운로드 (0) | 2023.06.20 |