jjzjj

c# - WebSocket 服务器未触发握手

coder 2023-08-11 原文

我正在尝试在 Unity 中使用简单的 HTML WebSocket,但套接字不会从服务器接收握手。

如果我的代码有问题,请告诉我。

index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
    <head>
        <title>Test</title>
        <script type="text/javascript" src="jquery.js"></script>
        <script type="text/javascript">
            var noSupportMessage = "Your browser cannot support WebSocket!";
            var ws;

            function appendMessage(message) {
                $('body').append(message);
            }

            function connectSocketServer() {
                var support = "MozWebSocket" in window ? 'MozWebSocket' : ("WebSocket" in window ? 'WebSocket' : null);

                if (support == null) {
                    appendMessage("* " + noSupportMessage + "<br/>");
                    return;
                }

                appendMessage("* Connecting to server ..<br/>");
                // create a new websocket and connect
                ws = new window[support]('ws://127.0.0.1:13000/websession');

                // when data is comming from the server, this metod is called
                ws.onmessage = function (evt) {
                    appendMessage("# " + evt.data + "<br />");
                };

                ws.onerror = function(evt){
                    appendMessage("# " + evt.data + "<br />");  
                };

                // when the connection is established, this method is called
                ws.onopen = function () {
                    appendMessage('* Connection open<br/>');
                    $('#messageInput').attr("disabled", "");
                    $('#sendButton').attr("disabled", "");
                    $('#connectButton').attr("disabled", "disabled");
                    $('#disconnectButton').attr("disabled", "");
                };

                // when the connection is closed, this method is called
                ws.onclose = function () {
                    appendMessage('* Connection closed<br/>');
                    $('#messageInput').attr("disabled", "disabled");
                    $('#sendButton').attr("disabled", "disabled");
                    $('#connectButton').attr("disabled", "");
                    $('#disconnectButton').attr("disabled", "disabled");
                }
            }

            function sendMessage() {
                if (ws) {
                    var messageBox = document.getElementById('messageInput');
                    ws.send(messageBox.value);
                    messageBox.value = "";
                }
            }

            function disconnectWebSocket() {
                if (ws) {
                    ws.close();
                }
            }

            function connectWebSocket() {
                connectSocketServer();
            }

            window.onload = function () {
                $('#messageInput').attr("disabled", "disabled");
                $('#sendButton').attr("disabled", "disabled");
                $('#disconnectButton').attr("disabled", "disabled");
            }

    </script>
    </head>
    <body>
        <input type="button" id="connectButton" value="Connect" onclick="connectWebSocket()"/> <input type="button" id="disconnectButton" value="Disconnect" onclick="disconnectWebSocket()"/> <input type="text" id="messageInput" /> <input type="button" id="sendButton" value="Send" onclick="sendMessage()"/> <br />
    </body>
</html>

Unity TCPServer.cs

using UnityEngine;
using System.Threading;
using System.Net.Sockets;
using System.IO;
using System;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Collections.Generic;

class TCPServer : MonoBehaviour
{
    public static List<SocketClient> ClientList = new List<SocketClient>();
    Thread mThread;

    void Start()
    {
        ThreadStart ts = new ThreadStart(Main);
        mThread = new Thread(ts);
        mThread.Start();
        print("Thread done...");
    }

    void Update(){
    }


    public static void Main()
    { 

        TcpListener socketServer = null;

        try
        {
            // Set the TcpListener on port 13000.
            Int32 port = 13000;
            IPAddress localAddr = IPAddress.Parse("127.0.0.1");

            // TcpListener server = new TcpListener(port);
            socketServer = new TcpListener(localAddr, port);

            print("Server has started on " + localAddr.ToString() + ":" + port.ToString() + "." + Environment.NewLine + "Waiting for a connection...");

            // Start listening for client requests.
            socketServer.Start();

            // counter
            int counter = 0;

            // Enter the listening loop.
            while(true) 
            {
                // check for any incoming pending connections
                // create new socket client for new connection
                TcpClient socketConnection = socketServer.AcceptTcpClient();

                counter++;

                DateTime now = DateTime.Now;

                //write message to console to indicate new connection
                print("New Client Connected - " + now.ToString("MM/dd/yyyy h:mm:ss tt"));

                // create new client object for this connection
                new SocketClient(socketConnection);
            }
        }
        catch(SocketException e)
        {
            print("SocketException: " + e);
        }
        finally
        {
            // Stop listening for new clients.
            socketServer.Stop();
        }


        print("Hit enter to continue...");
        Console.Read();
    }

    public static void CloseClient(SocketClient whichClient)
    {
        ClientList.Remove(whichClient);
        whichClient.Client.Close();

            // dispose of the client object
        whichClient.Dispose();
        whichClient = null;
        print("Client Disconnected");
    }

    public static void SendTextToClient(SocketClient sc, string text)
    {
        StreamWriter writer = new StreamWriter(sc.Client.GetStream());
            // check if client is still connected, then send the text string
        try
        {
            if (sc.Client.Connected)
            {
                writer.WriteLine(text);
                writer.Flush();
                writer = null;
            }
        }
        catch
        {
            CloseClient(sc);
        }

    }

    public static void LOG(string a ){
        print(a);
    }

    public static void SendBroadcast(string text)
    {
        StreamWriter writer;
            // loop through the array and send text to all clients
        foreach (SocketClient client in ClientList)
        {
            if (client.Client.Connected)
            {
                try
                {
                    writer = new StreamWriter(client.Client.GetStream());
                    writer.WriteLine(text);
                    writer.Flush();
                    writer = null;

                }
                catch
                {
                    CloseClient(client);
                }
            }
        }
    }


}

class SocketClient
{
    public TcpClient Client;
    StreamReader reader;
    StreamWriter writer;


    public SocketClient(TcpClient client)
    {
        Client = client;
        Thread clientThread = new Thread(new ThreadStart(StartClient));
        clientThread.Start();
    }


    private void StartClient()
    {
        TCPServer.ClientList.Add(this);

            // create a reader for this client
        reader = new StreamReader(Client.GetStream());
            // create a writer for this client
        writer = new StreamWriter(Client.GetStream());

        var headers = new Dictionary<string, string>();

        string line = "";
        while ((line = reader.ReadLine()) != string.Empty)
        {
            if (!string.IsNullOrEmpty(line))
            {
                var tokens = line.Split(new char[] { ':' }, 2);
                if (!string.IsNullOrEmpty(line) && tokens.Length > 1)
                {
                    headers[tokens[0]] = tokens[1].Trim();
                }
            }
        }

        String secWebSocketAccept = ComputeWebSocketHandshakeSecurityHash09(headers["Sec-WebSocket-Key"]);

            // send handshake to this client only
        writer.WriteLine("HTTP/1.1 101 Switching Protocols");
        writer.WriteLine("Upgrade: websocket");
        writer.WriteLine("Connection: Upgrade");
        writer.WriteLine("WebSocket-Origin: http://localhost");
        writer.WriteLine("WebSocket-Location: ws://127.0.0.1:13000/websession");
        writer.WriteLine("Sec-WebSocket-Accept: " + secWebSocketAccept);
        writer.WriteLine("Sec-WebSocket-Protocol: chat");
        writer.WriteLine("");
        writer.Flush();

        TCPServer.SendBroadcast("New Client Connected");

        Thread clientRun = new Thread(new ThreadStart(RunClient));
        clientRun.Start();
    }

    public static String ComputeWebSocketHandshakeSecurityHash09(String secWebSocketKey)
    {
        const String MagicKEY = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
        String secWebSocketAccept = String.Empty;

            // 1. Combine the request Sec-WebSocket-Key with magic key.
        String ret = secWebSocketKey + MagicKEY;

            // 2. Compute the SHA1 hash
        SHA1 sha = new SHA1CryptoServiceProvider(); 
        byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret));

            // 3. Base64 encode the hash
        secWebSocketAccept = Convert.ToBase64String(sha1Hash);

        return secWebSocketAccept;
    }


    private void RunClient()
    {
        try
        {
            string line = "";
            while (true)
            {
                line = reader.ReadLine();
                if (!string.IsNullOrEmpty(line))
                {
                    if(!string.IsNullOrEmpty(line.Trim(' '))){
                        TCPServer.SendBroadcast(line);
                    }
                }
            }
        }
        catch
        {
            TCPServer.CloseClient(this);
        }
    }

    public void Dispose()
    {
        System.GC.SuppressFinalize(this);
    }
}

最佳答案

WebSocket 不是原始 TCP。您需要一个 WebSocket 服务器。

如果您选择 WebSocket 服务器,您可以通过运行 AutobahnTestsuite 检查它是否符合 WebSocket 协议(protocol)标准 (IETF RFC6455) (在模糊客户端模式下)针对您的服务器。这将为您提供详细报告,如 this (包括 wirelog)遇到的问题。

披露:我是 Autobahn 的原作者,为 Tavendo 工作。

关于c# - WebSocket 服务器未触发握手,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20447752/

有关c# - WebSocket 服务器未触发握手的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  4. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  5. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  6. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  7. ruby-on-rails - 如何在 Rails Controller Action 上触发 Facebook 像素 - 2

    我有一个ruby​​onrails应用程序。我按照facebook的说明添加了一个像素。但是,要跟踪转化,Facebook要求您将页面置于达到预期结果时出现的转化中。即,如果我想显示客户已注册,我会将您注册后转到的页面作为成功对象进行跟踪。我的问题是,当客户注册时,在我的应用程序中没有登陆页面。该应用程序将用户带回主页。它在主页上显示了一条消息,所以我想看看是否有一种方法可以跟踪来自Controller操作而不是实际页面的转化。我需要计数的Action没有页面,它们是ControllerAction。是否有任何人都知道的关于如何执行此操作的gem、文档或最佳实践?这是进入布局文件的像素

  8. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  9. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  10. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

随机推荐