본문 바로가기
Web/Servlet

[Servlet] 웹 소켓을 이용한 채팅(update date - 2019-08-07)

by EricJeong 2019. 7. 23.

2019-11-06

서버 운영을 종료하였습니다.

 

 

2019-08-07 패치노트

 

서버 프리징 개선

웹 채팅 커넥션을 다수 잡아놓고 동시에 여러 처리를 진행하게 만들면 서버가 멈추는 증상을 해결하였습니다.

 

아마존 웹 서버 우분투 프리티어를 사용하고 있었는데, EC2의 성능이 문제가 되었던거 같네요.

서버를 로컬로 바꾸고 다시 배포를 하니 일단 100명수준 내에서는 작동에 문제가 없습니다.

 

접속주소는 아래쪽에 갱신해 두었습니다! 서버 접속이 되지 않을때는 댓글 혹은 제 이메일로 연락 부탁드립니다.

 

 

 

 

=======================================================================

 

 

접속할 수 있는 주소

http://175.203.27.33/DevEricServers/deveric/chat/chatpage.jsp

 

DevEric Chatting

 

175.203.27.33

 

 

IE는 보안정책상 지원하지 않습니다!

IE 브라우저 외 크롬, 파이어폭스 등으로 접속해주세요

 

IE는 구버전으로 접속하시면 같은 서버로 이용하실 수 있습니다.

구버전은 게시글 아래쪽에 접속 링크가 있습니다.

 

 

Eric Web Chat 0.2

 

위 주소로 접속하면 실시간 익명 채팅을 할 수 있습니다.

 

다만, 이용자가 많지 않은 관계로 채팅이 실제로 되는지 확인하고 싶다면

 

브라우저의 탭을 여러개 여신 후 위 주소로 각각 접속하시면 서로 채팅이 되는 것을 확인할 수 있습니다.

 

 

 

 

 

 

 

Update date - 2019/07/25

 

  • 인터페이스를 변경하였습니다.
  • 최대 채팅 인원을 999명으로 변경하였습니다.
  • 내가 보내는 메세지와 상대가 보내는 메세지를 구별하였습니다.
  • 메세지 밑에 보낸 시간이 뜨도록 수정하였습니다.
  • server가 보내는 메세지를 공지로 처리할 수 있도록 수정하였습니다

 

수정해야 하는 것들

  • 세션이 100ms  이내에 6개 이상 종료되면 서버에 오류가 발생하고 있습니다.
  • UI 개선이 필요합니다.
  • 접속한 유저 현황을 보여주고자 합니다.

 

다음에 만들 웹 채팅에서는 ...

  • 1:1기반 채팅을 만들고자 합니다.
  • 보내는 채팅 메세지를 암호화 하여 보내려고 합니다
  • DB와 연동하여 채팅 내역을 저장하려고 합니다.

 

 

WebChatServer.java

package deveric.webchat;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServlet;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import vo.ChatClient;


@ServerEndpoint("/webChatServer")
public class WebChatServer extends HttpServlet {
	private static Map<Session,ChatClient> users = Collections.synchronizedMap(new HashMap<Session, ChatClient>());
	
	
	
	@OnMessage
	public void onMsg(String message, Session session) throws IOException{
		String userName = users.get(session).getName();
		System.out.println(userName + " : " + message);
		
		synchronized (users) {
			Iterator<Session> it = users.keySet().iterator();
			while(it.hasNext()){
				Session currentSession = it.next();
				if(!currentSession.equals(session)){
					currentSession.getBasicRemote().sendText(userName + " : " + message);
				}
			}
		}
		
	}
	
	@OnOpen
	public void onOpen(Session session){
		String userName = "user";
		int rand_num = (int)(Math.random()*1000);
		
		
		ChatClient client = new ChatClient();
		System.out.println(session);
		client.setName(userName+rand_num);
		
		System.out.println(session + " connect");
		
		users.put(session, client);
		sendNotice(client.getName() + "님이 입장하셨습니다. 현재 사용자 " + users.size() + "명");
	}
	
	
	public void sendNotice(String message){
		String userName = "server";
		System.out.println(userName + " : " + message);
		
		synchronized (users) {
			Iterator<Session> it = users.keySet().iterator();
			while(it.hasNext()){
				Session currentSession = it.next();
				try {
					currentSession.getBasicRemote().sendText(userName + " : " + message);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	@OnClose
	public void onClose(Session session) {
		String userName = users.get(session).getName();
		users.remove(session);
		sendNotice(userName + "님이 퇴장하셨습니다. 현재 사용자 " + users.size() + "명");
	}

}

 

 

chatpage.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DevEric Chatting</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>


<style type="text/css">
	*{
		font-family: 나눔고딕;
	}
	#messageWindow{
		background: black;
		color: greenyellow;
	}
	#inputMessage{
		width:500px;
		height:20px
	}
	#btn-submit{
		background: white;
		background: #F7E600;
		width:60px;
		height:30px;
		color:#607080;
		border:none;
	}
	
	#main-container{
		width:600px;
		height:680px;
		border:1px solid black;
		margin:10px;
		display: inline-block;
		
	}
	#chat-container{
		vertical-align: bottom;
		border: 1px solid black;
		margin:10px;
		min-height: 600px;
		max-height: 600px;
		overflow: scroll;
		overflow-x:hidden;
		background: #9bbbd4;
	}
	
	.chat{
		font-size: 20px;
		color:black;
		margin: 5px;
		min-height: 20px;
		padding: 5px;
		min-width: 50px;
		text-align: left;
        height:auto;
        word-break : break-all;
        background: #ffffff;
        width:auto;
        display:inline-block;
        border-radius: 10px 10px 10px 10px;
	}
	
	.notice{
		color:#607080;
		font-weight: bold;
		border : none;
		text-align: center;
		background-color: #9bbbd4;
		display: block;
	}

	.my-chat{
		text-align: right;
		background: #F7E600;
		border-radius: 10px 10px 10px 10px;
	}
	
	#bottom-container{
		margin:10px;
	}
	
	.chat-info{
		color:#556677;
		font-size: 10px;
		text-align: right;
		padding: 5px;
		padding-top: 0px;

	}
	
	.chat-box{
		text-align:left;
	}
	.my-chat-box{
		text-align: right;
	}
	
	
	
</style>
</head>
<body>
	<div id="main-container">
		<div id="chat-container">
			
		</div>
		<div id="bottom-container">
			<input id="inputMessage" type="text">
			<input id="btn-submit" type="submit" value="전송" >
		</div>
	</div>
</body>
<script type="text/javascript">
	

	var textarea = document.getElementById("messageWindow");
	var webSocket = new WebSocket('ws://ec2-13-125-250-66.ap-northeast-2.compute.amazonaws.com:8080/DevEricServers/webChatServer');
	
	// 로컬에서 테스트할 때 사용하는 URL입니다.
// 	var webSocket = new WebSocket('ws://localhost/DevEricServers/webChatServer');
	var inputMessage = document.getElementById('inputMessage');
	
	webSocket.onerror = function(e){
		onError(e);
	};
	webSocket.onopen = function(e){
		onOpen(e);
	};
	webSocket.onmessage = function(e){
		onMessage(e);
	};
	
	
	function onMessage(e){
		var chatMsg = event.data;
		var date = new Date();
		var dateInfo = date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
		if(chatMsg.substring(0,6) == 'server'){
			var $chat = $("<div class='chat notice'>" + chatMsg + "</div>");
			$('#chat-container').append($chat);
		}else{
			var $chat = $("<div class='chat-box'><div class='chat'>" + chatMsg + "</div><div class='chat-info chat-box'>"+ dateInfo +"</div></div>");
			$('#chat-container').append($chat);
		}
		
		
		$('#chat-container').scrollTop($('#chat-container')[0].scrollHeight+20);
	}
	
	function onOpen(e){
		
	}
	
	function onError(e){
		alert(e.data);
	}
	
	function send(){
		var chatMsg = inputMessage.value;
		if(chatMsg == ''){
			return;
		}
		var date = new Date();
		var dateInfo = date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
		var $chat = $("<div class='my-chat-box'><div class='chat my-chat'>" + chatMsg + "</div><div class='chat-info'>"+ dateInfo +"</div></div>");
		$('#chat-container').append($chat);
		webSocket.send(chatMsg);
		inputMessage.value = "";
		$('#chat-container').scrollTop($('#chat-container')[0].scrollHeight+20);
	}
	
</script>

<script type="text/javascript">
	$(function(){
		$('#inputMessage').keydown(function(key){
			if(key.keyCode == 13){
				$('#inputMessage').focus();
				send();
			}
		});
		$('#btn-submit').click(function(){
			send();
		});
		
	})
</script>
</html>

 

 

 

 

 

 

 

======================== 이 밑은 구버전 입니다.  =======================

 

 

http://175.203.27.33/DevEricServers/deveric/chat/chatting.html

 

DevEric Chatting

 

175.203.27.33

 

 

WebChatServer.java

 

package deveric.webchat;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;


@ServerEndpoint("/webChatServer")
public class WebChatServer extends HttpServlet {
	private static Map<Session,String> users = Collections.synchronizedMap(new HashMap<Session, String>());
	
	@OnMessage
	public void onMsg(String message, Session session) throws IOException{
		String userName = users.get(session);
		System.out.println(userName + " : " + message);
		
		synchronized (users) {
			Iterator<Session> it = users.keySet().iterator();
			while(it.hasNext()){
				Session currentSession = it.next();
				if(!currentSession.equals(session)){
					currentSession.getBasicRemote().sendText(userName + " : " + message);
				}
			}
		}
		
	}
	
	@OnOpen
	public void onOpen(Session session) throws IOException{
		System.out.println(session);
		String userName = "user" + (int)(Math.random()*100);
		users.put(session, userName);
		sendNotice(userName + "님이 입장하셨습니다. 현재 사용자 " + users.size() + "명");
	}
	
	
	public void sendNotice(String message) throws IOException{
		String userName = "server";
		System.out.println(userName + " : " + message);
		
		synchronized (users) {
			Iterator<Session> it = users.keySet().iterator();
			while(it.hasNext()){
				Session currentSession = it.next();
				currentSession.getBasicRemote().sendText(userName + " : " + message);
			}
		}
	}

	@OnClose
	public void onClose(Session session) throws IOException{
		String userName = users.get(session);
		users.remove(session);
		sendNotice(userName + "님이 퇴장하셨습니다. 현재 사용자 " + users.size() + "명");
	}

}

 

 

chatting.html

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DevEric Chatting</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>


<style type="text/css">
	#messageWindow{
		background: black;
		color: greenyellow;
	}
	#inputMessage{
		width:500px;
	}
	#btn-submit{
		background: white;
		border : 1px solid red;
		width:60px;
		height:30px;
	}
</style>
</head>
<body>
	<fieldset>
		<textarea id="messageWindow" rows="30" cols="70" readonly="true"></textarea>
		<br><br>
		<input id="inputMessage" type="text">
<!-- 		onclick="send()" -->
		<input id="btn-submit" type="submit" value="전송" >
	</fieldset>
</body>
<script type="text/javascript">
	

	var textarea = document.getElementById("messageWindow");
	var webSocket = new WebSocket('ws://ec2-13-125-250-66.ap-northeast-2.compute.amazonaws.com:8080/DevEricServers/webChatServer');
// 	var webSocket = new WebSocket('ws://localhost/DevEricServers/webChatServer');
	var inputMessage = document.getElementById('inputMessage');
	
	webSocket.onerror = function(e){
		onError(e);
	};
	webSocket.onopen = function(e){
		onOpen(e);
	};
	webSocket.onmessage = function(e){
		onMessage(e);
	};
	
	
	function onMessage(e){
		textarea.value += event.data + "\n";
	}
	
	function onOpen(e){
		textarea.value += "==== Connected Eric Chat Server ===\n";
	}
	
	function onError(e){
		alert(e.data);
	}
	
	function send(){
		textarea.value += "나 : " + inputMessage.value + "\n";
		webSocket.send(inputMessage.value);
		inputMessage.value = "";
	}
	
</script>

<script type="text/javascript">
	$(function(){
		$('#btn-submit').click(function(){
			send();
		});
		
		$('#inputMessage').keydown(function(key){
			if(key.keyCode == 13){
				$('#inputMessage').focus();
				send();
			}
		});
	})
</script>
</html>

댓글