【问题标题】:C# TCP Socket stream message confusionC# TCP Socket 流消息混淆
【发布时间】:2016-12-22 14:59:22
【问题描述】:

我正在尝试编写 C# TCP 服务器并连接我的 Web 应用程序。这是我正在关注的教程。 Link

我设法启动了服务器,但我从我的 web 应用程序收到的消息是加密的。

C# 代码段

using System;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace Application
{
class MainClass
{
    public static void Main()
    {
        TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 8181);
        server.Start();

        Console.WriteLine("Server has started on 127.0.0.1:8181.{0}Waiting for a connection...", Environment.NewLine);

        TcpClient client = server.AcceptTcpClient();
        Console.WriteLine("A client connected.");

        NetworkStream stream = client.GetStream();
        while (true)
        {
            while (!stream.DataAvailable) ;

            Byte[] bytes = new Byte[client.Available];

            stream.Read(bytes, 0, bytes.Length);

            String data = Encoding.UTF8.GetString(bytes);

            //handshaking
            if (new Regex("^GET").IsMatch(data))
            {
                Byte[] response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + Environment.NewLine
                    + "Connection: Upgrade" + Environment.NewLine
                    + "Upgrade: websocket" + Environment.NewLine
                    + "Sec-WebSocket-Accept: " + Convert.ToBase64String(
                        SHA1.Create().ComputeHash(
                            Encoding.UTF8.GetBytes(
                                new Regex("Sec-WebSocket-Key: (.*)").Match(data).Groups[1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
                            )
                        )
                    ) + Environment.NewLine
                    + Environment.NewLine);

                stream.Write(response, 0, response.Length);
            }
            else 
            {
                Console.WriteLine(data);
            }
        }
    }
}
}

HTML 片段

<form>
<input id="textField1" type="text" style="margin: 0 5px; width: 200px; height: 40px;" placeholder="Enter data">
<button id="sendTextField1" type="button" class="btn btn-info">Send</button>
  </form>
  <script type="text/javascript">
    var start = function () {
    var wsImpl = window.WebSocket || window.MozWebSocket;
    window.ws = new wsImpl('ws://127.0.0.1:8181/');

    ws.onmessage = function (evt) {
      console.log(evt.data);
    };
    ws.onopen = function () {
      console.log("Connected");
    };
    ws.onclose = function () {
      console.log("Closed");
    };

    document.getElementById("sendTextField1").onclick = function() {
      sendToSocket(document.getElementById('textField1').value);
    };

    function sendToSocket(value){
      console.log("Sending value to socket " + value + " ");
      ws.send(value);
    };
}
window.onload = start;

这是我从控制台得到的

我尝试将消息编码为另一种格式,但完全没有运气。

据此stackoverflow user,

消息不是以原始格式发送的,但它们具有数据框架。

这与我现在遇到的问题有关吗?我是否需要找到一种方法来解构从应用中获得的数据?

【问题讨论】:

  • 顺便说一句,写那篇文章的人不知道正确处理 TCP 流; bleugh - DataAvailable 上的热循环,试图解析数据包(通过 DataAvailable)而不是逻辑帧......非常非常糟糕的示例代码。
  • 作为记录,您链接到的示例确实显示了掩码代码(“解码算法”),但是......那里有很多令人讨厌的东西。 ..
  • while (true) { while (!stream.DataAvailable); ... 让我想哭
  • 哈哈大佬,我也不清楚,Mozilla官方教程,觉得对新手有用

标签: c# html sockets tcp


【解决方案1】:

嗯,这不是一个好的开始:

String data = Encoding.UTF8.GetString(bytes);

握手后发送的数据不是 UTF8 文本。它的一部分是,但有二进制标头,还有一些东西(至少在 RFC6455 中 - 如果您的客户端使用 Hixie-76 可能不是)称为"Client-to-Server Masking",这意味着数据确实是经过处理的(这是,IIRC ,主要是为了避免代理服务器出现问题,而不是加密)。

还有你循环握手的问题,但是:你只握手一次。

基本上,web-sockets 协议非常微妙(并且:某些浏览器/版本的实现很糟糕/不正确)。除非您有充分的理由*,否则我强烈建议您使用库而不是尝试手动编写。 Microsoft 在框架中提供了一定程度的支持,这应该会有所帮助。


*=我已经这样做了,但是对于我们的场景,关键的设计原因是可扩展性——我们目前有 464515 个打开的 web-socket 连接,而 MS 实现只是不会削减它。如果有帮助,我们编写了代码freely available。

【讨论】:

  • 感谢您指出我在握手部分的错误,我尝试使用您提供的库后会修改它。
  • @J.Doe 实际上,因为该库是为愚蠢的大容量场景设计的,它更注重性能而不是友好性;除非您是为了一点挑战而玩游戏,否则使用几乎任何其他库 可能会更容易:)
  • @J.Doe 实际上,看起来我们确实把一个很好的例子放在一起:github.com/StackExchange/NetGain#websocket-server-example
  • 您好,先生,我试过 NetGain,效果很好。实际上,我们的网络应用程序旨在提供需要我们发送二进制数据的实时视频流和播放功能。 NetGain 是为此目的而设计的吗?
  • @J.Doe 是的,NetGain 将允许您发送二进制数据。我无法具体说明它对视频流的适用程度。特别是,传递给Send 的message 可以是string 或byte[],但是,对于您的场景,您可能希望使用缓冲池或类似的。显示的示例是“请求/响应”示例,但在实际使用中您不需要它 - 有一些方法可以在不需要请求的情况下向客户端发送数据(这就是您获得我添加的更新的方式在这里评论!)
猜你喜欢
  • 2013-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多