WebSocketとJavaによって完了したメッセージプッシュ機能は、サーバーTomcat7.0によって使用されます。いくつかのことは自分で考慮されており、それらが適切であるか不適切かはわかりません。私を許して、それらを指摘してください。
簡単に言えば、顧客Aは顧客Bにメッセージを送信できますが、拡張できる多くの場所があります。
例えば
1.データベースに参加した後、Aがメッセージを送信した場合、顧客Bがオンラインではない場合、サーバーはメッセージをデータベースに保存します。顧客Bがオンラインになった後、メッセージが取得され、顧客Bに送信されます
2。サーバーは、任意のクライアントにメッセージを送信することもできます。
プログラムの実行効果のスクリーンショットは次のとおりです(Chrome、Sogou、およびFirefoxでテストされています):コードは最後に与えられます
まず、ブラウザと表示を開き、名前を入力します。ここに私はSOARに入ります
2番目のブラウザを開くとき、ここにビルを入力します
これは、私がハロービルを送る場合、私は請求書に舞い上がります、[送信]をクリックします
別のブラウザで見ることができます
WebSocket
1. WebSocketとは何ですか?
WebSocketは、クライアントとサーバー間のリアルタイム通信を解決するために生成されるテクノロジーです。本質は、HTTP/HTTPSプロトコルを介して手作業でデータを交換するためのTCP接続を作成することです。
その後、サーバーとクライアントは、このTCP接続を通じてリアルタイムで通信します。
2。WebSocketの利点
過去には、ポーリングを使用してプッシュテクノロジーを実装しました。特性時間間隔で、ブラウザはリクエストを自動的に発行し、サーバーのメッセージを積極的に引き戻します。この場合、サーバーに常にリクエストを送信する必要があります。ただし、HTTP要求のヘッダーは非常に長く、そこに含まれるデータはわずかな値であり、多くの帯域幅とサーバーのリソースを占める可能性があります。帯域幅とサーバーのリソースを大量に消費します。
WebSocket APIの最大のことは、サーバーとクライアントが特定の時間範囲内でいつでも情報を互いにプッシュできることです。接続を確立した後、サーバーはデータをクライアントに積極的に送信できます。
さらに、サーバーとクライアントの間で交換されるヘッダー情報は非常に小さいです。
Ajaxテクノロジーではクライアントがリクエストを開始する必要があるため、WebSocketはAjax(またはXHR)モードでの通信に限定されません。
Ajax、Comet、WebSocket、およびWebSocketメッセージの詳細な紹介については、http://www.shaoqun.com/a/54588.aspx Web Design] Ajax、Comet、およびWebSocketを参照できます。
将来時間があれば、書き留めます。
3. WebSocketの使用方法
クライアント
ソケットを作成した後、WebSocketをサポートするブラウザで。 Onopen、Onmessage、Onclose、つまりOnerrorの4つのイベントを通じてソケットに応答できます。
簡単な例
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(console!);};};};1.VAR WS = new 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)};
クライアントがサーバーから送信されたメッセージを受信すると、オンメサージイベントがトリガーされます。パラメーターEVT.DATAには、サーバーが送信したデータが含まれています。
4.ws.onclose = function(evt){console.log(websocketclosed!); };
クライアントがサーバーから送信された接続を閉じるリクエストを受信したとき、オンクロースイベントがトリガーされます
5.ws.onerror = function(evt){console.log(websocketError!); };
接続、処理、受信、およびデータの送信が失敗すると、Onerrorイベントがトリガーされます
すべての操作がイベントによってトリガーされているため、UIがブロックされず、UIの応答時間が短くなり、ユーザーエクスペリエンスが向上します。
サーバー側
現在、node.js、jetty、tomcatなど、WebSocketをサポートするサーバーソフトウェアがたくさんあります。
ここでは、Tomat 7.0とEclipse4.2を使用しています
Tomcat、最初にWebSocketを使用して、関連する瓶をインポートします
Tomcat7が提供するWebSocketに関連するクラスはすべてパッケージorg.apache.catalina.websocketにあります(パッケージorg.apache.catalina.websocketの実装はファイルCatalina.jarに含まれています。
ここでは、すべてのTomcatをインポートするだけです
Build Path-> configure build path-> librarise-> bilding-> add biburt-> server runtime-> apache tomcat v7.0
画像
また、次のパッケージをインポートします
org.apache.catalina.websocket.messageinboundをインポートします。
org.apache.catalina.websocket.streaminboundをインポートします。
org.apache.catalina.websocket.wsoutboundをインポートします。
org.apache.catalina.websocket.websocketservletをインポートします。
2つのクラスが必要です
最初のものは、WebSocketリクエストを処理するために使用されます
2番目のものは、特定の各WebSocketタスクを処理するために使用されます
最初のカテゴリ
Public Class SocketServerはWebSocketServletを拡張します{
private static final long serialversionuid = 1l;
//…
@オーバーライド
保護されたstreaminbound createwebsocketinbound(string arg0、
httpservletrequest arg1){
// TODO自動生成方法スタブ
新しいChatWeBsocket(ユーザー)を返します。
}
}
このサーブレットは、websocketservletから継承し、createwebsocketinboundメソッドを実装します。この方法は、2番目のクラスのインスタンスを返します。
2番目のカテゴリ
Public Class ChatWebsocketはMessageInboundを拡張します{
@オーバーライド
保護されたvoid ontextmessage(charbuffer message)throws ioexception {
}
@オーバーライド
保護されたvoid onopen(wsoutbound outbound){
}
@オーバーライド
保護されたvoid onclose(int status){
}
@オーバーライド
保護されたvoid onbinarymessage(bytebuffer arg0)はioexceptionをスローします{
}
//残りは少しです
}
保護されたvoid ontextmessage(charbuffer message)throws ioexception {}
テキストメッセージ応答
保護されたvoid onbinarymessage(bytebuffer arg0)はioexception {}をスローします
バイナリメッセージ応答
保護されたvoid onopen(wsoutbound outbound){}
接続を確立することでトリガーされたイベント
保護されたvoid onclose(int status){}
接続を閉じるときに発生したイベント
4。プログラムコード
HTMLパーツ
<!doctype html>
<html>
<head>
<メタcharset = utf-8>
<script type = text/javascript src = js/jquery.js> </script>
<script type = text/javascript src = js/socket.js> </script>
<title> un unt ittitled document </title>
</head>
<スクリプト言語= javascript>
</script>
<body>
<表>
<tr>
<td>メッセージ</td>
<td> <入力タイプ=テキストID =メッセージ> </td>
</tr>
<tr>
<td> name </td>
<td> <入力タイプ=テキストid = othername> </td>
</tr>
<tr>
<TD> <入力ID = SENDBUTTON TYPE =ボタン値= send onclick = click disabled = true>
</input> </td>
</tr>
</table>
<スクリプト>
</script>
</body>
</html>
JSパート(jQueryパーツについての説明はありません)
var username = window.prompt(名前を入力:);
document.write(welcome <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();
send(msg);
}
function send(data)
{
console.log(send:+data);
ws.send(data);
}
function startwebsocket()
{
ws = new WebSocket(ws:// + location.host +/websocket/socketserver);
ws.onopen = function(){
console.log(成功オープン);
$(#sendbutton).attr(disabled、false);
};
ws.onmessage = function(event)
{
console.log(受信:+event.data);
handLedata(event.data);
};
ws.onclose = function(event){
Console.log(クライアント通知ソケットが閉じている、イベント);
};
}
関数ハンドラタ(データ)
{
var vals = data.split(/t);
var msgtype = vals [0];
switch(msgtype)
{
ケース名:
var msg = vals [1];
var mes = name+/t+msg+_+username;
send(mes);
壊す;
ケースMSG:
var val2s = vals [1] .split(_);
var from = val2s [0];
var message = val2s [2];
アラート(+:+メッセージ);
壊す;
デフォルト:
壊す;
}
}
Javaパート
java.io.ioexceptionをインポートします。
java.nio.bytebufferをインポートします。
java.nio.charbufferをインポートします。
javax.servlet.http.httpservletrequestをインポートします。
java.util.setをインポートします。
java.util.concurrent.copyonwritearraysetをインポートします。
org.apache.catalina.websocket.messageinboundをインポートします。
org.apache.catalina.websocket.streaminboundをインポートします。
org.apache.catalina.websocket.wsoutboundをインポートします。
org.apache.catalina.websocket.websocketservletをインポートします。
Public Class SocketServerはWebSocketServletを拡張します{
private static final long serialversionuid = 1l;
パブリックファイナルセット<ChatWebsocket>ユーザー= new CopyOnWritearRayset <ChatWebsocket>();
public static int usernumber = 1;
@オーバーライド
保護されたstreaminbound createwebsocketinbound(string arg0、
httpservletrequest arg1){
// TODO自動生成方法スタブ
新しいChatWeBsocket(ユーザー)を返します。
}
Public Class ChatWebsocketはMessageInboundを拡張します{
プライベート文字列ユーザー名;
プライベートセット<ChatWeBsocket>ユーザー= new CopyOnWritearRayset <ChatWeBsocket>();;
public chatwebsocket(){
}
public chatwebsocket(set <ChatWebsocket>ユーザー){
this.users = users;
}
@オーバーライド
保護されたvoid ontextmessage(charbuffer message)throws ioexception {
//ここで処理されているのはテキストデータです
}
public void onmessage(string data){
string [] val1 = data.split(// t);
if(val1 [0] .equals(name))
{
string [] val2 = val1 [1] .split(_);
for(chatwebsocketユーザー:ユーザー){
if(user.username.equals(val2 [0])){
user.username = val2 [1];
}
}
}
else if(val1 [0] .equals(msg))
{
string [] val2 = val1 [1] .split(_);
for(chatwebsocketユーザー:ユーザー){
if(user.username.equals(val2 [1])){
試す {
Charbuffer temp = charbuffer.wrap(data);
user.getwsoutbound()。writeTextmessage(temp);
} catch(ioException e){
// TODO自動生成キャッチブロック
e.printstacktrace();
}
}
}
}
それ以外
{
System.out.println(error);
}
}
@オーバーライド
保護されたvoid onopen(wsoutbound outbound){
// this.connection = connection;
this.username =# + string.valueof(usernumber);
usernumber ++;
試す {
文字列メッセージ= name + /t + this.username;
Charbuffer buffer = charbuffer.wrap(message);
this.getwsoutbound()。writeTextmessage(buffer);
} catch(ioException e){
// TODO自動生成キャッチブロック
e.printstacktrace();
}
users.add(this);
}
@オーバーライド
保護されたvoid onclose(int status){
users.remove(this);
}
@オーバーライド
保護されたvoid onbinarymessage(bytebuffer arg0)はioexceptionをスローします{
}
}
}
説明する
ここでの私の考えは
1アクセスするとき、各ユーザーは最初に自分の名前を入力してから、サーバーに接続要求を送信する必要があります。
2サーバーがクライアントの接続要求を受け入れた後、新しいChatWeBsocket(ユーザー)になります。このリクエストを処理し、オンラインユーザーリストに追加します。現時点では、サーバーは顧客の名前をまだ把握していません。このユーザーの名前は#1であり、サーバーはクライアントに名前 + /t +#1を送信します、あなたの名前は何ですか?
3クライアントがこのメッセージを受信すると、サーバーがその名前が何であるかを尋ねていることがわかっているため、クライアントは名前+/t+#1+_+独自の名前をサーバーに送信します(私の名前はxxx)
4このメッセージを受信した後、サーバーは#1に基づいて現在オンラインユーザーリストを検索し、#1を顧客の名前に置き換えて、サーバーが顧客の名前を知るようにします。
5顧客が出発すると、サーバーはオンクラスイベントをトリガーし、サーバーはオンラインリストから現在のユーザーを削除します。
写真を使用してこのようなものを描く(ひどく描かれている、-_- !!)
コード
JS
ws = new WebSocket(ws:// + location.host +/websocket/socketserver);
サーバーに接続します
Java
保護されたstreaminbound createwebsocketinbound(string arg0、
httpservletrequest arg1){
// TODO自動生成方法スタブ
新しいChatWeBsocket(ユーザー)を返します。
}
このリクエストを処理するチャットウェブソケットを作成し、ChatWebsocketオブジェクトのOnopenイベントをトリガーします
@オーバーライド
保護されたvoid onopen(wsoutbound outbound){
// this.connection = connection;
this.username =# + string.valueof(usernumber);
usernumber ++;
試す {
文字列メッセージ= name + /t + this.username;
Charbuffer buffer = charbuffer.wrap(message);
this.getwsoutbound()。writeTextmessage(buffer);
} catch(ioException e){
// TODO自動生成キャッチブロック
e.printstacktrace();
}
users.add(this);
}
このクライアントの名前を仮定して、想定された名前の名前+/t+をクライアントに送信し、現在接続されているクライアントリストにクライアントを追加する
JS
関数ハンドラタ(データ)
{
var vals = data.split(/t);
var msgtype = vals [0];
switch(msgtype)
{
ケース名:
var msg = vals [1];
var mes = name+/t+msg+_+username;
send(mes);
壊す;
//………
}
}
サーバーから送信されたメッセージを受け入れて処理し、サーバーがその名前が何であるかを尋ねたので、想定された名前+_+をサーバーに送信しました。
Java
public void onmessage(string data){
string [] val1 = data.split(// t);
if(val1 [0] .equals(name))
{
string [] val2 = val1 [1] .split(_);
for(chatwebsocketユーザー:ユーザー){
if(user.username.equals(val2 [0])){
user.username = val2 [1];
}
}
}
//………
}
クライアントから送信されたメッセージを処理して受け入れ、クライアントがその名前に返信したことを発見したので、以前に想定された名前に基づいて現在接続されているクライアントリストで検索し、仮名を本名に変換します
JS
関数sendmessage()
{
var othername = $(#othername).val();
var msg = msg/t+username+_+othername+_+$(#message).val();
send(msg);
}
クライアントは他の人との会話を開始し、メッセージ形式は次のとおりです。
Java
public void onmessage(string data){
///…………
else if(val1 [0] .equals(msg))
{
string [] val2 = val1 [1] .split(_);
for(chatwebsocketユーザー:ユーザー){
if(user.username.equals(val2 [1])){
試す {
Charbuffer temp = charbuffer.wrap(data);
user.getwsoutbound()。writeTextmessage(temp);
} catch(ioException e){
// TODO自動生成キャッチブロック
e.printstacktrace();
}
}
}
}
///…………
}
メッセージは顧客によって送信されることがわかります。相手の名前に従って、現在接続されている顧客リストで検索し、メッセージを彼に送信します。
JS
関数ハンドラタ(データ)
{
var vals = data.split(/t);
var msgtype = vals [0];
switch(msgtype)
{
///…
ケースMSG:
var val2s = vals [1] .split(_);
var from = val2s [0];
var message = val2s [2];
アラート(+:+メッセージ);
壊す;
デフォルト:
壊す;
}
}
それは他の顧客から送信されたメッセージであり、アラートによって表示されたことがわかりました
Java
@オーバーライド
保護されたvoid onclose(int status){
users.remove(this);
}
顧客が去ったことを発見し、接続された顧客リストから顧客を削除します
改善する場所
1.クライアントAがBにメッセージを送信し、Bがオンラインでない場合、メッセージはデータベースに保存できます。 Bがオンラインであることがわかった場合、データベースから取得され、Bに送信されます。
2サーバーが名前を送信すると、タイムアウトメカニズムを追加できます。クライアントが一定期間内に呼ばれるものに返信しない場合、クライアントはオンラインリストからクライアントを削除できます。