Client 소스

<%@ 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>Insert title here</title>
<style type="text/css">
input#chat {
 width: 410px
}

#console-container {
 width: 400px;
}

#console {
 border: 1px solid #CCCCCC;
 border-right-color: #999999;
 border-bottom-color: #999999;
 height: 170px;
 overflow-y: scroll;
 padding: 5px;
 width: 100%;
}

#console p {
 padding: 0;
 margin: 0;
}
</style>
</head>
<body>
<div>
 <p><input type="text" placeholder="type and press enter to chat" id="chat" /></p>
 <div id="console-container">
  <div id="console"></div>
 </div>
</div>

<script type="text/javascript">

var Chat = {};

Chat.socket = null;

Chat.connect = (function(host) {
 
 if( "WebSocket" in window) {
  Chat.socket = new WebSocket(host);
 } else if( "MozWebSocket" in window ){
  Chat.socket = new MozWebSocket(host);
 } else {
  Console.log("Error : 지원하지 않는 브라우저 입니다.");
  return;
 }
 
 Chat.socket.onopen = function() {
  Console.log("정보 : WebSocket 오픈!");
  document.getElementById("chat").onkeydown = function(event) {
   if( event.keyCode == 13 ) {
    Chat.sendMessage();
   }
  };
 };
 
 Chat.socket.onclose = function() {
  document.getElementById("chat").onkeydown = null;
  Console.log("정보 : WebSocket 오픈 종료!");
 };
 
 Chat.socket.onmessage = function(message) {
  console.log(message);
  Console.log(message.data);
 };
 
});

Chat.initialize = function() {
 if( window.location.protocol == "http:") {
  Chat.connect("ws://" + window.location.host + "/websocket/chat");
 } else {
  Chat.connect("wss://" + window.location.host + "/websocket/chat");
 }
};

Chat.sendMessage = (function() {
 var message = document.getElementById("chat").value;
 if( message != "") {
  Chat.socket.send(message);
        document.getElementById("chat").value = '';
 }
});

var Console = {};

Console.log = (function(message) {
 var console = document.getElementById("console");
 var p = document.createElement("P");
 p.style.wordWrap = "break-word";
 p.innerHTML = message;
 
 console.appendChild(p);
 
 while (console.childNodes.length > 25) {
        console.removeChild(console.firstChild);
    }

    console.scrollTop = console.scrollHeight;
});

Chat.initialize();
</script>
</body>
</html>

 

Server Source

package com.test.websocket.service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ServerEndpoint(value = "/websocket/chat")
// 클라이언트가 접속할 때 사용될 URI
public class ChatService {

 private static final Logger logger = LoggerFactory.getLogger(ChatService.class);

 private static final String GUEST_PREFIX = "Guest";

 private static final AtomicInteger connectionIds = new AtomicInteger(0);

 private static final Map<String, Session> sessionMap = new HashMap<String, Session>();

 private final String nickname;

 // 클라이언트가 새로 접속할 때마다 한개의 Session 객체가 생성된다.
 // Session 객체를 컬렉션에 보관하여 두고 해당 클라이언트에게 데이터를 전송할 때마다 사용한다
 private Session session;

 public ChatService() {

  // 클라이언트가 접속할 때마다 서버측에서는 Thread 가 새로 생성되는 것을 확인할 수 있다
  String threadName = "Thread-Name:" + Thread.currentThread().getName();

  // getAndIncrement()은 카운트를 1 증가하고 증가되기 전의 숫자를 리턴한다
  nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
  logger.info("생성자:" + threadName + ", " + nickname);
 }

 @OnOpen
 public void start(Session session) {
  logger.info("클라이언트 접속 : " + session);
  this.session = session;
  sessionMap.put(nickname, session);

  String message = String.format("* %s %s", nickname, " 접속");
  broadcast(message);
 }

 @OnClose
 public void close() {
  sessionMap.remove(nickname);
  String message = String.format("* %s %s", nickname, " 종료");
  broadcast(message);
 }

 @OnMessage
 public void message(String message) {
  String threadName = "Thread-name : " + Thread.currentThread().getName();
  logger.info("메시지 도착 : " + threadName + ", " + nickname);
  
  logger.info("메시지  : " + message );
  if (null == message && "".equals(message))
   return;

  String filteredMessage = String.format("%s: %s", nickname, message);
  // Guest0의 메시지는 특정 클라이언트(Guest2)에게만 전달하는 경우
  //  if (this.nickname.equals("Guest0")) {
  //   sendToOne(filteredMessage, sessionMap.get("Guest2"));
  //  } else // 현재 접속된 모든 클라이언트에게 메시지를 전달하는 경우
  //  {
  //   broadcast(filteredMessage);
  //  }
  broadcast(filteredMessage);
 }

 @OnError
 public void onError(Throwable t) throws Throwable {
  System.err.println("오류/세션제거(" + nickname + "):Chat Error: " + t.toString());
  sessionMap.remove(this.nickname);
 }

 private void broadcast(String msg) {
  
  Set<String> keys = sessionMap.keySet();
  Iterator<String> it = keys.iterator();

  while (it.hasNext()) {
   String key = it.next();
   Session s = sessionMap.get(key);

   try {
    
    s.getBasicRemote().sendText(msg);
    
   } catch (IOException e) {

    sessionMap.remove(key);

    try {
     s.close();
    } catch (IOException e1) {
     e1.printStackTrace();
    }

    String message = String.format("* %s %s", key, "has been disconnected.");
    broadcast(message);
   }

  }

 }

 private void sendToOne(String msg, Session ses) {

  try {
   ses.getBasicRemote().sendText(msg);
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

}

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<script src="/jquery/jquery-1.10.2.js"></script>
<script type="text/javascript">
/**
 * 이미지 썸네일을 불러오는 function
 * @param html : input 필드의 dom을 인자로 받는다. 물론 타입은 file
 * @param $target : 불러온 이미지를 적용할 jquery 객체.
 **/
function getThumbnail(html, $target) {
   if (html.files && html.files[0]) {
       var reader = new FileReader();
       reader.onload = function (e) {
           $target.css('background-image', 'url(\"' + e.target.result + '\")');
       }
       reader.readAsDataURL(html.files[0]);
   }
}

</script>
<input type="file" id="file" name="file" onchange="getThumbnail(this,$('#image'))" />
<div id="image" style="width: 300px; height: 300px; border: 1px solid #000000"></div>
</body>
</html>

'HTML5' 카테고리의 다른 글

Websocket를 통한 Chat  (0) 2015.07.08
XMLHttpRequest level2를 사용하기 위한 Tomcat7 CORS 설정  (0) 2015.06.01
지오로케이션 API 사용하기  (0) 2015.05.29

CORS : Cross-Origin Request Sharding

(참조 : http://www.w3.org/TR/cors/)

 

기존에는 Same-Origin Policy 정책에 의해 타 도메인간 송수신이 금지되어 있었던 부분이 있었습니다.

 

HTML5에서는 이를 수정하여 CORS 라는 규칙하에 타 도메인간 송수신을 할 수 있는 표준을 발표하였습니다.

 

여기서 CORS를 사용하기 위하여 Tomcat에 설정을 수정해줘야 합니다.

 

$CATALINA_HOME/conf/web.xml 파일에 아래의 Filter을 추가하여 줍니다.

<filter>
     <filter-name>CorsFilter</filter-name>
     <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
 </filter>
 <filter-mapping>
     <filter-name>CorsFilter</filter-name>
     <url-pattern>/*</url-pattern>
 </filter-mapping>

가장 심플하게 설정한 내용입니다.

자세한 설정정보는  https://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#CORS_Filter 을 참조하시면 됩니다.

 

'HTML5' 카테고리의 다른 글

Websocket를 통한 Chat  (0) 2015.07.08
이미지 첨부시 미리보기 처리  (0) 2015.07.06
지오로케이션 API 사용하기  (0) 2015.05.29

이제 시작하는 HTML5입니다.

책을 보면서 하나씩 정리하려고 합니다.

CANVAS, AUDIO 등등 여러가지가 있지만 우선 난 다 뛰어 넘고..ㅋㅋ

그건 나중에 다시 필요 할때..^ ^

재미 있는거 부터 해야 실증이 안나니까..요..

그래서 지도 부터 시작..........

구글 MAP을 사용하는 방식에 대해서는 따로 설명하지 않도록 하겠습니다.

 

 

전체 소스코드  

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>GEO TEST</title>
</head>
<body onload="checkBrowser()">

<div class="info">
  <span id="support">HTML5 지오로케이션을 지원하지 않는 브라우저 입니다.</span>
</div>

<div id="map_canvas" style="width:100%; height:600px"></div>

<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=구글에서발급받은Key&sensor=TRUE"></script>
<script type="text/javascript">

var mapOptions = {
 zoom: 17,
 mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);

function checkBrowser() {
 if( navigator.geolocation ) {
  document.getElementById("support").innerHTML="HTML5 지오로케이션을 지원하는 브라우저 입니다.";
  navigator.geolocation.getCurrentPosition(updateLocation, handlerLocationError);
 }
}

function updateLocation(position) {

 var latitude = position.coords.latitude;
 var longitude = position.coords.longitude;
 var accuracy = position.coords.accuracy;

 map.setCenter(new google.maps.LatLng(latitude, longitude));
}

function handlerLocationError(error) {
 alert( error.code );
}
</script>
</body>
</html>

 

 

HTML5 에서 달라졌다고 할 수 있는 부분이 많지만 현 소스에서 보면 DOCTYPE 선언 부분이 가장 심플해 졌습니다.

기존 선언은

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

이런 식으로 쭉 나열 했었지만 HTML5는

<!DOCTYPE html>

이렇게 선언함으로서 끝납니다.

 

 

문자셋 역시 심플해져서

기존에는

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

이렇게 썼던것을

<meta charset="UTF-8">

이와 같이 선언합니다.

정말 심플해진거 같아요..ㅋ

 

 

그럼 넘어가서 HTML5 지오로케이션 API 사용법입니다.

HTML5에서는 navigator 를 제공하고 navigator.geolocation을 객체를 생성하여 위치정보를 가져 올 수 있도록 처리 하였습니다.

function checkBrowser() {
 if( navigator.geolocation ) {
  document.getElementById("support").innerHTML="HTML5 지오로케이션을 지원하는 브라우저 입니다.";
  navigator.geolocation.getCurrentPosition(updateLocation, handlerLocationError);
 }
}

해당 소스는 지오로케이션이 지원이 되는 Browser를 체크 하는 소스 입니다.

Geolocation 에서 위치를 가져오는 형태는 두가지가 존재 합니다.

단발성 위치 요청(getCurrentPosition()) 과 반복적인 위치요청(watchPosition()) 의 두가지가 있습니다.

단발성 위치 요청은 웹호출시 한번만 호출 되어지지만 반복적 위치 요청은 주기적으로 위치를 호출 하게 되어 있습니다.

반복적인 위치 요청을 하고자 할경우에는 getCurrentPosition을 watchPosition으로 바꿔주시기만 하면 됩니다.

 

 

단발성 위치 요청

void getCurrentPosition(PositionCallback successCallback,        // 필수 입력

PositionErrorCallback errorCallback,    //Error 발생시 호출 되는 Handler(옵션)

PositionOptions options);                    //옵션

전체 소스에서는 단발성 위치 요청을 사용하였습니다.

 

 

필수 매개변수인 successCallback을 구현한 소스입니다.

function updateLocation(position) {

 var latitude = position.coords.latitude;            // 위도
 var longitude = position.coords.longitude;      //경도
 var accuracy = position.coords.accuracy;     //정확도

 map.setCenter(new google.maps.LatLng(latitude, longitude));
}

실재 위치정보를 수신하는 handler입니다

변수로 선언된 position에 해당 위치의 정보가 담겨져 있습니다.

위치정보에 담겨 져 있는 위도와 경도를 구글MAP에 설정해 주면 완료 입니다.

참 쉽죠~~~^ ^?

 

 

errorCallback에 해당하는 소스 입니다.

function handlerLocationError(error) {
 alert( error.code );
}

구찮아서 Error Code만 출력했습니다..ㅡㅡ;;

 

 

Error Code는 총 4가지가 있습니다.

 

UNKNOWN_ERROR(에러코드 0) : 어떠한 에러 코드에도 해당하지 않을 경우입니다. 해당내용을 확인하고자 할경우 error.message 속성으로 확인이 가능합니다.

PERMISSION_DENIED(에러코드 1) : 사용자가 위치정보 공유를 허가하지 않은경우 발생합니다.

POSITION_UNAVAILABLE(에러코드 2) : 사용자의 위치를 판단을 실팽하였을 경우 발생합니다.

TIMEOUT(에러코드 3) : 옵션에 타임아웃이 설정되어 있거나 제한범위를 벗어난 지역에서 발생합니다.

 

마지막 옵션은 아직 정확히 공부하지 않아 추후 하게 되면...^ ^ 그때나 해당 페이지를 수정하도록 하겠습니다..ㅋ

 

 

 

 위의 Source를 실행해 보면

 아래와 같이 나오게 됩니다..ㅋ 근데........... 오차가 좀 많이 심하군요..ㅡㅡ

 

'HTML5' 카테고리의 다른 글

Websocket를 통한 Chat  (0) 2015.07.08
이미지 첨부시 미리보기 처리  (0) 2015.07.06
XMLHttpRequest level2를 사용하기 위한 Tomcat7 CORS 설정  (0) 2015.06.01

+ Recent posts