このトピックでは、WebSocketをサポートするブラウザーとASP.NETアプリケーションの間でWebSocket接続を整理する方法を説明します。
この記事では、接続を整理し、接続されたクライアントにメッセージを送信する方法について説明します。 また、記事の最後に、動作中のアプリケーションのソースコードへのリンクがあります。
この記事とアプリケーションは、これがすべてどのように機能するか、ASP.NETとWebSocketをどのように接続できるかの例に過ぎず、現在の形式の実装ガイドであるとはほとんど主張していませんが、基本をよく示し、改善することができます。
WebSocketが必要な理由とその利点は何であるかを伝える必要はないと思います。 個人的には、JavaScriptで本格的なクライアントアプリケーションを
コメット (優れた記事は
こちら )や定期的なリクエストのようなトリックなしで作成するためには、彼らは非常に不足していると思います。
しかし、特に、このテクノロジーは、ChromeブラウザーでCometを使用する際の小さな「問題」の解決策を見つけることに真剣に興味を持ちました。
Cometテクノロジーを使用して整理する場合、Chromeなどの一部のブラウザーは、ページが常にロードされているように動作し、同じChromeが「リクエストを待機中」と書き込み、カーソルは常に待機状態のままになります。
これはもちろん不快です。
そして、これに適した技術があり、それを研究することが可能であるときに、回避策を使用する理由は簡単です。
接続自体。 クライアント側(JavaScript)では、ブラウザーは特別なWebSocketクラスを提供します。
ここに彼の説明
があります
これを使用して、サーバーへの接続を開き、必要なイベントをサブスクライブし、接続後にサーバーにメッセージを送信します。
var sock;
function connectToServer() {
try {
sock = new WebSocket( "ws://localhost:8181/websock" );
sock.onopen = sockOpen;
sock.onerror = sockError;
sock.onclose = sockClosed;
sock.onmessage = sockMessage;
} catch (e) {
log( "error:" + e);
}
}
* This source code was highlighted with Source Code Highlighter .
上記のコードからわかるように、サーバーはlocalhost:8181で接続を待機します。
この例では、すべてのサブスクライバー関数がテキストフィールドに情報を表示するだけで、サーバーには何も送信しません。 接続後、これは非常に簡単ですが、この例では、物事を少しだけ複雑にします。
サーバー。 ASP.NETアプリケーション/ Webサイトはリクエストを処理するときにのみ機能し、接続を常に待機する必要があるため、別のスレッドを開始する必要があります。 Global.asaxでやってみましょう。 ストリームとサーバーは、特別なクラシックによって処理されます。
void Application_Start( object sender, EventArgs e)
{
WebSocks.WebSockServer.Start();
}
void Application_End( object sender, EventArgs e)
{
WebSocks.WebSockServer.End();
}
* This source code was highlighted with Source Code Highlighter .
Start関数では、接続を待機するThreadを単に開始し、Endではそれをクリーンアップします。 これらはすべてソースコードで詳しく見ることができます。これについては記事の最後で説明します。
したがって、以下では、最も重要な関数のコードですが、まず、ナビゲートしやすくするために何が起こるかを簡単に説明します。
- 新しいクライアントが参加します(今のところ、一度に1人ずつサービスを提供します)
- 私たちは顧客の握手を受け入れます
- ハンドシェイクを送信します。 その後、接続が確立されたと見なすことができます。
- Hello World!という行を送信します。
コード自体は次のとおりです。
public static void Listen()<br> {<br> // <br> Listener = new TcpListener(IPAddress.Loopback, PortNumber);<br> Listener.Start();<br><br> while ( true )<br> {<br> // <br> using (Socket client = Listener.AcceptSocket()) <br> using (NetworkStream stream = new NetworkStream(client)) <br> using (StreamReader reader = new StreamReader(stream)) <br> using (StreamWriter writer = new StreamWriter(stream)) <br> {<br><br> string clientHandshake = String .Empty; <br> string currentRead = null ; <br> string clientOrigin = "" ; <br><br> while (currentRead != "" )<br> {<br> // handshake <br> currentRead = reader.ReadLine();<br> clientHandshake += currentRead + Environment.NewLine;<br><br> // <br> if (currentRead.StartsWith( "Origin" ))<br> {<br> // <br> int valueStartIndex = currentRead.IndexOf( ':' ) + 1;<br> clientOrigin = currentRead.Substring(valueStartIndex, currentRead.Length - valueStartIndex);<br> }<br> }<br><br> // (Handshake) <br> writer.WriteLine( "HTTP/1.1 101 Web Socket Protocol Handshake" );<br> writer.WriteLine( "Upgrade: WebSocket" );<br> writer.WriteLine( "Connection: Upgrade" );<br><br> // Origin . <br> // " ", , <br> // , . <br> writer.WriteLine( String .Format( "WebSocket-Origin: {0}" , clientOrigin));<br> writer.WriteLine( "WebSocket-Location: ws://localhost:8181/websock" );<br> writer.WriteLine( "" );<br> writer.Flush();<br><br> // / . <br> Thread.Sleep(100);<br> <br> // <br> byte [] first = new byte [] { 0x00 };<br> byte [] last = new byte [] { 0xFF };<br> <br> // ( ) <br> client.Send(first);<br><br> // Hello World <br> client.Send( Encoding .UTF8.GetBytes( "Hello world!" ));<br><br> // ( ) <br> client.Send(last);<br> }<br> }<br> } <br><br> * This source code was highlighted with Source Code Highlighter .
そして、ここに約束されたソースがあります。
dl.dropbox.com/u/3945288/WebSocketsArticle.zip
これは最も単純な例であり、クライアント処理時のマルチスレッド化の欠如などの欠点があります。 また、たとえば、ユーザーのセッションへのアクセスを提供するなど、さらなる開発の余地もあります。
記事が気に入って誰かを助けてくれたら嬉しいです。トピックを発展させて、もっと書いてみようと思います。
UPD:コメントでは、以前のリビジョン75、現在の76の実装にセキュリティが追加されていることに気付きました。 私は両方のエディションで動作するバージョンを作ろうとしますが、明らかに今日はそうではありません。
ベストプラクティスの共有を求められた方のために、 ここにすべてをアップロードしました 。 理論的には、すべてが機能するはずですが、機能しません:)、どこかで横棒ですが、脳はもう気づきません。
UPD2:約束どおり、バージョン75と76の両方をサポートするバージョンがあります。