0

私は WebSocket API の初心者です。サーバーにローカルで接続しようとしていますが、接続が閉じられたというメッセージが表示されます。誰が私が間違っているのか教えてもらえますか?

それが私のコードです:

サーバ

using System.Net.Sockets;
using System.Net;
using System.IO;
using System;
class Program
{
    static void Main(string[] args)
    {
        var listener = new TcpListener(IPAddress.Loopback, 8181);
    listener.Start();
    while (true)
    {
        Console.WriteLine("Listening...");
        using (var client = listener.AcceptTcpClient())
        using (var stream = client.GetStream())
        using (var reader = new StreamReader(stream))
        using (var writer = new StreamWriter(stream))
        {

            string line = null, key = "", responseKey = "";
            string MAGIC_STRING = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
            while (line != "")
            {
                line = reader.ReadLine();
                if (line.StartsWith("Sec-WebSocket-Key:"))
                {
                    key = line.Split(':')[1].Trim();
                }
            }

            if (key != "")
            {
                key += MAGIC_STRING;
                using (var sha1 = SHA1.Create())
                {
                    responseKey = Convert.ToBase64String(sha1.ComputeHash(Encoding.ASCII.GetBytes(key)));
                }
            }

            // send handshake to the client
            writer.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake");
            writer.WriteLine("Upgrade: WebSocket");
            writer.WriteLine("Connection: Upgrade");
            writer.WriteLine("WebSocket-Origin: http://localhost:8080");
            writer.WriteLine("WebSocket-Location: ws://localhost:8181/websession");
            if (!String.IsNullOrEmpty(responseKey))
                writer.WriteLine("Sec-WebSocket-Accept: " + responseKey);
            writer.WriteLine("");
            Console.ReadLine();
            writer.Flush();

        }//using
        Console.WriteLine("Finished");
    }//while

    }
}

クライアント

     <!DOCTYPE HTML>
       <html>
       <head><title></title>
          <script type="text/javascript">

       function WebSocketTest() {
          var msg = document.getElementById("msg");
            if ("WebSocket" in window) {
             msg.innerHTML="WebSocket is supported by your Browser!";
        // Let us open a web socket
        var ws = new WebSocket("ws://localhost:8181/websession");
        ws.onopen = function () {
            // Web Socket is connected, send data using send()
             msg.innerHTML="connection open";
            //ws.send("Message to send");
            //msg.innerHTML="Message is sent...";
        };
        ws.onclose = function () {
            // websocket is closed.
            msg.innerHTML = "Connection is closed...";
        };

        ws.onerror = function(error){
            console.log('Error detected: ' + error);
        };
        ws.onmessage = function (evt) {
            var received_msg = evt.data;
            msg.innerHTML="Message is received...";
        };

    }
    else {
        // The browser doesn't support WebSocket
        msg.innerHTML="WebSocket NOT supported by your Browser!";
    }
   }
   </script>
     </head>
       <body>
       <div id="sse">
        <a href="javascript:WebSocketTest()">Run WebSocket</a><br />
         <p id="msg"></p>
       </div>
        </body> 
           </html>

任意の解決策をいただければ幸いです。ありがとうございます:)

4

2 に答える 2

0

これは、どの仕様でも有効なWebSocket応答ではありません。最初のWeb-Socket応答では、Web-Socketサーバーであることを証明するために、応答ヘッダーの一部としていくつかの数値を処理する必要があります。読み取りと書き込みを行うヘッダー、および実行するクランチは、Webソケットのバージョン(hibi / hixie 76 / rfc)によって異なります。実際には、サーバーがクライアントのヘッダーを使用しているように見えます。

たとえば、RFC6455(13)応答は次のように開始します。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: {crunch some numbers}

Hixie-76の応答は異なり、上記には省略したビットがあることに注意してください。

RFC6455仕様から:

ハンドシェイクが受信されたことを証明するために、サーバーは2つの情報を取得し、それらを組み合わせて応答を形成する必要があります。最初の情報は|Sec-WebSocket-Key|から取得されます クライアントハンドシェイクのヘッダーフィールド:

 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

このヘッダーフィールドの場合、サーバーは値(ヘッダーフィールドに存在する値、たとえば、base64でエンコードされた[RFC4648]バージョンから先頭と末尾の空白を差し引いたもの)を取得し、これをグローバル一意識別子(GUID、[RFC4122 ])文字列形式の「258EAFA5-E914-47DA-95CA-C5AB0DC85B11」。これは、WebSocketプロトコルを理解しないネットワークエンドポイントによって使用される可能性は低いです。次に、この連結のSHA-1ハッシュ(160ビット)[FIPS.180-3]、base64エンコード([RFC4648]のセクション4を参照)がサーバーのハンドシェイクで返されます。

于 2013-01-31T10:51:16.667 に答える
0

JavaScriptコードがWebサーバーに接続した後。C# はすべての using ステートメントを実行し、すべての行をファイルに出力します。その後、すべての using ステートメントが閉じられ、生成されたクライアントが破棄され、接続が閉じられます。
この問題の簡単な (しかし汚い) 修正方法は、using ステートメントの最後に "Console.Readline" を追加することです。ただし、これには注意してください。プロセスがハングします。
クライアントを受け入れる TcpClients の詳細については、msdnを参照してください。
そこにある例では、一度に 1 つの接続しか許可されていないことに注意してください。
最後の発言: Marc が提案したような websocket 接続を受け入れるためのライブラリが存在します。

于 2013-01-31T11:41:33.400 に答える