WebSocket과 Java가 완료 한 메시지 푸시 기능은 서버 TomCat7.0에서 사용됩니다. 어떤 것들은 혼자서 고려되며, 그들이 적절한 지, 부적절한 지 모르겠습니다. 저를 용서하고 그들을 지적하십시오.
간단히 말해서 고객 A는 고객 B에게 메시지를 보낼 수 있지만 확장 할 수있는 곳이 많이 있습니다.
예를 들어
1. 데이터베이스에 가입 한 후 A가 메시지를 보내면 고객 B가 온라인 상태가 아닌 경우 서버는 메시지를 데이터베이스에 저장합니다. 고객 B가 온라인 상태 인 경우 메시지를 검색하여 고객 B로 전송합니다.
2. 서버는 모든 클라이언트에게 메시지를 보낼 수도 있습니다.
프로그램 실행 효과의 스크린 샷은 다음과 같습니다 (Chrome, Sogou 및 Firefox에서 테스트) : 코드는 끝에 제공됩니다.
먼저, 우리는 브라우저를 열고 디스플레이를 통해 귀하의 이름을 입력합니다. 여기에 나는 Soar에 들어갑니다
두 번째 브라우저를 열 때 여기에 Bill을 입력합니다
제가 Hello Bill을 보내면 청구서에 솟아 오르고 보내는 것입니다.
다른 브라우저에서 볼 수 있습니다
WebSocket
1. WebSocket이란 무엇입니까?
WebSocket은 클라이언트와 서버 간의 실시간 커뮤니케이션을 해결하기 위해 생성 된 기술입니다. 본질은 http/https 프로토콜을 통해 핸드 쉐이킹 후 데이터를 교환하기위한 TCP 연결을 만드는 것입니다.
그 후 서버와 클라이언트는이 TCP 연결을 통해 실시간으로 통신합니다.
2. WebSocket의 장점
과거에는 폴링을 사용하여 푸시 기술을 구현했습니다. 특성 시간 간격에서 브라우저는 자동으로 요청을 발행하고 서버의 메시지를 적극적으로 철회합니다. 이 경우 서버에 요청을 지속적으로 보내야합니다. 그러나 HTTP 요청의 헤더는 매우 길며, 그 안에 포함 된 데이터는 작은 값 일 수 있으며, 이는 많은 대역폭 및 서버 리소스를 차지할 것입니다. 많은 대역폭 및 서버 리소스를 소비합니다.
WebSocket API의 가장 큰 장점은 서버와 클라이언트가 주어진 시간 범위 내에서 언제든지 정보를 서로 푸시 할 수 있다는 것입니다. 연결을 설정 한 후 서버는 클라이언트에게 데이터를 적극적으로 전송할 수 있습니다.
또한 서버와 클라이언트간에 교환 된 헤더 정보는 매우 작습니다.
Ajax 기술은 클라이언트가 요청을 시작 해야하는 반면 WebSocket 서버와 클라이언트는 정보를 서로 푸시 할 수 있기 때문에 WebSocket은 AJAX (또는 XHR) 모드의 커뮤니케이션에만 국한되지 않습니다.
Ajax, Comet, WebSocket 및 WebSocket 메시지에 대한 자세한 소개는 http://www.shaoqun.com/a/aspx 웹 디자인] Ajax, Comet 및 WebSocket을 참조하십시오.
미래에 시간이 있다면, 나는 그것을 쓸 것입니다.
3. WebSocket을 사용하는 방법
고객
소켓을 작성한 후 WebSocket을 지원하는 브라우저에서. Onopen, OnMessage 및 OnClose, 즉 OnError의 네 가지 이벤트를 통해 소켓에 응답 할 수 있습니다.
간단한 예
var ws = new WebSocket (ws : // localhost : 8080); ws.onopen = function () {console.log (Open); ws.send (hello);}; ws.onmessage = function (evt) {console.log (evt.data)}; ws.onclose = function (evt) {console.log (webSocketClosed!);}; ws.onerror = function (evt) {console.log (webSockerError!);1.var ws = 새로운 WebSocket (ws : // localhost : 8080);
WebSocket 객체를 신청하기 위해 매개 변수는 연결 해야하는 서버의 주소입니다. HTTP 프로토콜과 마찬가지로 WebSocket 프로토콜의 URL은 ws : //에서 시작되며 보안 WebSocket 프로토콜은 wss : //에서 시작합니다.
ws.send (Hello);
서버에 메시지를 보내는 데 사용됩니다
2.ws.onopen = function () {console.log (Open)};
WebSocket이 성공적으로 생성되면 OnOpen 이벤트가 트리거됩니다.
3.ws.onmessage = function (evt) {console.log (evt.data)};
클라이언트가 서버에서 전송 된 메시지를 받으면 OnMessage 이벤트가 트리거됩니다. 매개 변수 EVT.Data에는 서버가 전송 한 데이터가 포함되어 있습니다.
4.ws.onclose = function (evt) {console.log (WebSocketClosed!); };
클라이언트가 서버에서 보낸 연결을 닫으 겠다는 요청을 받으면 OnClose 이벤트가 트리거됩니다.
5.ws.onerror = function (evt) {console.log (WebSocketError!); };
연결, 처리, 수신 및 데이터 전송이 실패하면 OnError 이벤트가 트리거됩니다.
모든 작업이 이벤트에 의해 트리거되므로 UI가 차단되지 않도록 UI가 더 빠른 응답 시간과 더 나은 사용자 경험을 가질 수 있도록합니다.
서버 측
요즘 Node.js, Jetty, Tomcat 등과 같은 WebSocket을 지원하는 많은 서버 소프트웨어가 있습니다.
여기에서 Tomat 7.0 및 eclipse4.2를 사용하고 있습니다
Tomcat, WebSocket을 먼저 사용하여 관련 JAR을 가져옵니다
Tomcat7에서 제공하는 WebSocket과 관련된 클래스는 모두 패키지 org.apache.catalina.websocket에 있습니다 (패키지 org.apache.catalina.websocket의 구현은 Catalina.jar 파일에 포함되어 있습니다.
여기서 우리는 모든 Tomcat을 가져옵니다
빌드 경로-> 빌드 경로 구성-> Librarise-> Add Library-> 서버 런타임-> Apache Tomcat v7.0
영상
또한 다음 패키지를 가져 오십시오
import org.apache.catalina.websocket.messageInbound;
import org.apache.catalina.websocket.streaminbound;
import org.apache.catalina.websocket.wsoutbound;
import org.apache.catalina.websocket.websocketServlet;
두 개의 수업이 필요합니다
첫 번째는 WebSocket 요청을 처리하는 데 사용됩니다
두 번째는 각 특정 WebSocket 작업을 처리하는 데 사용됩니다.
첫 번째 범주
Public Class SocketServer 확장 webSocketServlet {
개인 정적 최종 최종 긴 SerialversionUID = 1L;
//…
@보수
보호 된 스트림 바운드 CreateWebsocketInbound (String Arg0,
httpservletrequest arg1) {
// TODO 자동 생성 메소드 스텁
새로운 chatwebsocket (사용자)을 반환합니다.
}
}
이 서블릿은 WebSocketServlet에서 상속되어 CreateWeBsocketInbound 방법을 구현합니다. 이 메소드는 두 번째 클래스의 인스턴스를 반환합니다.
두 번째 범주
공개 클래스 chatwebsocket 확장 messageInbound {
@보수
보호 된 void ontextMessage (charBuffer 메시지) IoException {
}
@보수
보호 된 void onopen (wsoutbound outbound) {
}
@보수
보호 된 void onclose (int status) {
}
@보수
보호 된 void OnbinaryMessage (Bytebuffer arg0)는 ioexception {
}
// 나머지는 조금만 있습니다
}
보호 된 void ontextMessage (charbuffer 메시지) IoException {}
문자 메시지 응답
보호 된 void OnbinaryMessage (Bytebuffer Arg0)는 ioexception {} 던지기
이진 메시지 응답
보호 된 void onopen (wsoutbound outbound) {}
연결을 설정하여 트리거 된 이벤트
보호 된 void onclose (int status) {}
연결을 닫을 때 이벤트가 발생했습니다
4. 프로그램 코드
HTML 부분
<! doctype html>
<html>
<헤드>
<meta charset = utf-8>
<script type = text/javaScript src = js/jquery.js> </script>
<script type = text/javaScript src = js/socket.js> </script>
<title> 제목의 문서 </title>
</head>
<스크립트 언어 = javaScript>
</스크립트>
<body>
<테이블>
<tr>
<td> 메시지 </td>
<td> <입력 유형 = 텍스트 id = 메시지> </td>
</tr>
<tr>
<td> 이름 </td>
<td> <입력 유형 = 텍스트 ID = OtherName> </td>
</tr>
<tr>
<td> <입력 ID = SendButton 유형 = 버튼 값 = onclick = 클릭 비활성화 = true>
</입력> </td>
</tr>
</테이블>
<cript>
</스크립트>
</body>
</html>
JS 부분 (jQuery Part에 대한 설명 없음)
var username = window.prompt (이름을 입력 :);
document.write (환영 <p id =/username/>+username+</p>);
if (! window.websocket && window.mozwebsocket)
Window.websocket = Window.MozWebSocket;
if (! window.websocket)
경고 (지원 없음);
var ws;
$ (document) .ready (function () {
$ (#sendButton) .attr (disabled, false);
$ (#sendButton) .click (sendMessage);
startwebsocket ();
})
함수 sendMessage ()
{
var OtherName = $ (#OtherName) .val ();
var msg = msg/t+username+_+othername+_+$ (#message) .val ();
보내기 (msg);
}
함수 보내기 (데이터)
{
Console.log (send :+data);
ws.send (데이터);
}
함수 startwebsocket ()
{
ws = new WebSocket (ws : // + location.host +/websocket/socketserver);
ws.onopen = function () {
Console.log (성공 오픈);
$ (#sendButton) .attr (disabled, false);
};
ws.onmessage = function (이벤트)
{
Console.log (수신 :+event.data);
handledata (event.data);
};
ws.onclose = function (이벤트) {
Console.log (클라이언트 알림 소켓이 닫혔습니다, 이벤트);
};
}
함수 handledata (데이터)
{
var vals = data.split (/t);
var msgtype = vals [0];
스위치 (msgtype)
{
사례 이름 :
var msg = vals [1];
var mes = name+/t+msg+_+사용자 이름;
보내기 (mes);
부서지다;
Case Msg :
var val2s = vals [1] .split (_);
var from = val2s [0];
var 메시지 = val2s [2];
경고 (+:+메시지에서);
부서지다;
기본:
부서지다;
}
}
자바 부분
import java.io.ioexception;
import java.nio.bytebuffer;
import java.nio.charbuffer;
import javax.servlet.http.httpservletrequest;
java.util.set import;
import java.util.concurrent.copyonwritearrayset;
import org.apache.catalina.websocket.messageInbound;
import org.apache.catalina.websocket.streaminbound;
import org.apache.catalina.websocket.wsoutbound;
import org.apache.catalina.websocket.websocketServlet;
Public Class SocketServer 확장 webSocketServlet {
개인 정적 최종 최종 긴 SerialversionUID = 1L;
공개 최종 세트 <chatwebsocket> users = new copyonwritearRayset <chatwebsocket> ();
공개 정적 int usernumber = 1;
@보수
보호 된 스트림 바운드 CreateWebsocketInbound (String Arg0,
httpservletrequest arg1) {
// TODO 자동 생성 메소드 스텁
새로운 chatwebsocket (사용자)을 반환합니다.
}
공개 클래스 chatwebsocket 확장 messageInbound {
개인 문자열 사용자 이름;
개인 세트 <chatwebsocket> users = new copyonwritearRayset <chatwebsocket> () ;;
public chatwebsocket () {
}
public chatwebsocket (set <chatwebsocket> users) {
this.users = 사용자;
}
@보수
보호 된 void ontextMessage (charBuffer 메시지) IoException {
// 여기에서 처리되는 것은 텍스트 데이터입니다
}
public void onMessage (문자열 데이터) {
문자열 [] val1 = data.split (// t);
if (val1 [0] .equals (이름))
{
문자열 [] val2 = val1 [1] .split (_);
for (chatwebsocket user : user) {
if (user.username.equals (val2 [0]) {
user.username = val2 [1];
}
}
}
else if (val1 [0] .equals (msg))
{
문자열 [] val2 = val1 [1] .split (_);
for (chatwebsocket user : user) {
if (user.username.equals (val2 [1])) {
노력하다 {
charbuffer temp = charbuffer.wrap (data);
user.getwsoutBound (). writeTextMessage (temp);
} catch (ioexception e) {
// TODO 자동 생성 캐치 블록
e.printstacktrace ();
}
}
}
}
또 다른
{
System.out.println (오류);
}
}
@보수
보호 된 void onopen (wsoutbound outbound) {
// this.connection = 연결;
this.username = # + string.valueof (usernumber);
UserNumber ++;
노력하다 {
문자열 메시지 = 이름 + /t + this.username;
charbuffer buffer = charbuffer.wrap (메시지);
this.getWsoutBound (). writeTextMessage (버퍼);
} catch (ioexception e) {
// TODO 자동 생성 캐치 블록
e.printstacktrace ();
}
user.add (this);
}
@보수
보호 된 void onclose (int status) {
user.remove (this);
}
@보수
보호 된 void OnbinaryMessage (Bytebuffer arg0)는 ioexception {
}
}
}
설명하다
내 생각은 여기에 있습니다
1 액세스 할 때 각 사용자는 먼저 자신의 이름을 입력 한 다음 서버에 연결 요청을 보내야합니다.
2 서버가 클라이언트의 연결 요청을 수락 한 후 새로운 chatwebsocket (사용자); 이 요청을 처리하고 온라인 사용자 목록에 추가합니다. 현재 서버는 아직 고객의 이름을 모릅니다. 이 사용자의 이름 인 #1의 이름을 가정하고 서버는 클라이언트에 이름 + /t + #1을 보내며 이름은 무엇입니까?
3 클라이언트 가이 메시지를 받으면 서버가 이름이 무엇인지 묻고 있음을 알 수 있으므로 클라이언트는 이름+/t+#1+_+자체 이름을 서버에 보냅니다 (내 이름은 xxx).
4이 메시지를 수신 한 후 서버는 #1을 기준으로 현재 온라인 사용자 목록에서 검색하고 #1을 고객 이름으로 대체하여 서버가 고객의 이름을 알 수 있도록합니다.
5 고객이 떠날 때 서버는 OnClose 이벤트를 트리거하고 서버는 온라인 목록에서 현재 사용자를 제거합니다.
그림을 사용하여 이와 같은 것을 그려냅니다 (나쁘게 그리기, -_- !!)
암호
JS
ws = new WebSocket (ws : // + location.host +/websocket/socketserver);
서버에 연결하십시오
자바
보호 된 스트림 바운드 CreateWebsocketInbound (String Arg0,
httpservletrequest arg1) {
// TODO 자동 생성 메소드 스텁
새로운 chatwebsocket (사용자)을 반환합니다.
}
이 요청을 처리 할 chatwebsocket을 만들고 chatwebsocket 객체의 Onopen 이벤트를 트리거합니다.
@보수
보호 된 void onopen (wsoutbound outbound) {
// this.connection = 연결;
this.username = # + string.valueof (usernumber);
UserNumber ++;
노력하다 {
문자열 메시지 = 이름 + /t + this.username;
charbuffer buffer = charbuffer.wrap (메시지);
this.getWsoutBound (). writeTextMessage (버퍼);
} catch (ioexception e) {
// TODO 자동 생성 캐치 블록
e.printstacktrace ();
}
user.add (this);
}
이 클라이언트의 이름을 가정하고, 가정 된 이름+/t+의 이름을 클라이언트에 보내고, 현재 연결된 클라이언트 목록에 클라이언트를 추가합니다.
JS
함수 handledata (데이터)
{
var vals = data.split (/t);
var msgtype = vals [0];
스위치 (msgtype)
{
사례 이름 :
var msg = vals [1];
var mes = name+/t+msg+_+사용자 이름;
보내기 (mes);
부서지다;
// ………
}
}
서버가 보낸 메시지를 수락하고 처리하고 서버가 이름이 무엇인지 물었 음을 알게되므로 이름+/t+를 서버로 보냈습니다.
자바
public void onMessage (문자열 데이터) {
문자열 [] val1 = data.split (// t);
if (val1 [0] .equals (이름))
{
문자열 [] val2 = val1 [1] .split (_);
for (chatwebsocket user : user) {
if (user.username.equals (val2 [0]) {
user.username = val2 [1];
}
}
}
// ………
}
클라이언트가 보낸 메시지를 처리하고 수락하고 클라이언트가 이름으로 답장을 받았으므로 이전에 가정 된 이름을 기준으로 현재 연결된 클라이언트 목록에서 검색하고 가명을 실명으로 바꾸십시오.
JS
함수 sendMessage ()
{
var OtherName = $ (#OtherName) .val ();
var msg = msg/t+username+_+othername+_+$ (#message) .val ();
보내기 (msg);
}
클라이언트는 다른 사람과 대화를 시작하고 메시지 형식은 다음과 같습니다. MSG+자체 이름+_+이름+_+메시지
자바
public void onMessage (문자열 데이터) {
/// …………
else if (val1 [0] .equals (msg))
{
문자열 [] val2 = val1 [1] .split (_);
for (chatwebsocket user : user) {
if (user.username.equals (val2 [1])) {
노력하다 {
charbuffer temp = charbuffer.wrap (data);
user.getwsoutBound (). writeTextMessage (temp);
} catch (ioexception e) {
// TODO 자동 생성 캐치 블록
e.printstacktrace ();
}
}
}
}
/// …………
}
메시지는 고객이 전송하는 것으로 나타났습니다. 상대방의 이름에 따르면 현재 연결된 고객 목록에서 검색하고 메시지를 그에게 보내십시오.
JS
함수 handledata (데이터)
{
var vals = data.split (/t);
var msgtype = vals [0];
스위치 (msgtype)
{
///…
Case Msg :
var val2s = vals [1] .split (_);
var from = val2s [0];
var 메시지 = val2s [2];
경고 (+:+메시지에서);
부서지다;
기본:
부서지다;
}
}
다른 고객이 보낸 메시지 인 것으로 밝혀졌으며 Alert를 통해 표시되었습니다.
자바
@보수
보호 된 void onclose (int status) {
user.remove (this);
}
고객을 발견하고 연결된 고객 목록에서 고객을 제거하십시오.
개선 장소
1. 클라이언트 A가 B로 메시지를 보내고 B가 온라인 상태가 아닌 경우 메시지를 데이터베이스에 저장할 수 있습니다. B가 온라인 상태 인 경우 데이터베이스에서 검색하여 B로 전송됩니다.
2 서버가 이름을 보내면 타임 아웃 메커니즘을 추가 할 수 있습니다. 클라이언트가 특정 기간 내에 호출 된 내용에 응답하지 않으면 클라이언트는 온라인 목록에서 클라이언트를 삭제할 수 있습니다.