C#WebSocket版本8+;服务器通信

C#WebSocket版本8+;服务器通信,c#,asp.net,html,websocket,C#,Asp.net,Html,Websocket,我一直在开发一款类似于hello world的WebSocket应用程序,看看能否在VS 2010中使用它。客户端代码非常简单,在Safari中工作得非常好,因为Safari仍然在WebSocket 76协议上运行 另一方面,GoogleChrome运行的是更新的Sec WebSocket版本代码,这更为复杂。我从code plex项目中“借用”了一些代码作为基础,以使其适用于旧的76和75协议: 然后我继续升级我在那里找到的代码,直到它可以执行新的握手(在下面的代码中)。我最终遇到了一个难题,

我一直在开发一款类似于hello world的WebSocket应用程序,看看能否在VS 2010中使用它。客户端代码非常简单,在Safari中工作得非常好,因为Safari仍然在WebSocket 76协议上运行

另一方面,GoogleChrome运行的是更新的Sec WebSocket版本代码,这更为复杂。我从code plex项目中“借用”了一些代码作为基础,以使其适用于旧的76和75协议:

然后我继续升级我在那里找到的代码,直到它可以执行新的握手(在下面的代码中)。我最终遇到了一个难题,似乎找不到任何帮助,那就是与Sec WebSocket版本8+套接字的通信。以前你可以在开头加上一个0x00,在结尾加上一个0xFF,然后再加上tada!成功了!但现在显然还有更多的工作要做来解决安全问题。当我通过调试代码发送消息时,我可以看出套接字正在关闭,我在几个地方看到,当chrome接收到它不理解的消息时,它喜欢关闭套接字

然后我发现了这篇文章:这家伙和我有同样的问题,但我似乎无法将他的回答者发布的伪代码翻译成C。有人能帮我吗

客户端代码:

<div id="ComLog" style="height:600px;">


</div>
<input type="button" onclick="javascript:connectToServer();" value='connect' />

<script type="text/javascript">
    var sock;
    function connectToServer() {
        try {
            sock = new WebSocket("ws://localhost:8181/websock");
            //sock = new WebSocket("ws://192.168.0.100:8181/websock");

            //sock = new WebSocket("ws://websockets.org:8787");

            sock.onopen = sockOpen;
            sock.onerror = sockError;
            sock.onclose = sockClosed;
            sock.onmessage = sockMessage;
        } catch (e) {
            log("error:" + e);
        }
    }

    function sockOpen() {
        log("connected");
    }

    function sockError(error, p2) {
        log("socket error!");
    }

    function sockClosed() {
        log("socket closed");
    }

    function sockMessage(event) {
        log("<b>Server:</b> " + event.data);
    }

    function log(msg) {
        var txtLog = document.getElementById("ComLog");
        txtLog.innerHTML += msg + "</br>";
    }
</script>

这看起来是诚实的权利;它与我的工作代码非常相似(它只处理32位长度,因此缺少>>32及以上):

之后,它只写入有效负载(如果有)。由于您是从服务器向客户机写入数据,因此实际上不需要担心出站掩码,因此总是
127
。但是,如果您正在接受传入的消息,那么您非常需要担心掩码

注意:.Windows8上的NET4.5在
HttpListener
和ASP.NET中内置了WebSocket支持;在此之前,另一种方法可能是研究SuperWebSocket


重新编辑:您已经选择了自己的数据!请尝试:

bool IsFinal = true;
int OpCode = 1;
int? Mask = null;
byte[] payload = Encoding.UTF8.GetBytes(Msg);
int PayloadLength = payload.Length;
byte[] buffer = new byte[64]; // for working out the header

int offset = 0;
buffer[offset++] = (byte)((IsFinal ? 128 : 0) | ((int)OpCode & 15));
if (PayloadLength > ushort.MaxValue)
{ // write as a 64-bit length
    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | 127);
    buffer[offset++] = 0;
    buffer[offset++] = 0;
    buffer[offset++] = 0;
    buffer[offset++] = 0;
    buffer[offset++] = (byte)(PayloadLength >> 24);
    buffer[offset++] = (byte)(PayloadLength >> 16);
    buffer[offset++] = (byte)(PayloadLength >> 8);
    buffer[offset++] = (byte)(PayloadLength);
}
else if (PayloadLength > 125)
{ // write as a 16-bit length
    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | 126);
    buffer[offset++] = (byte)(PayloadLength >> 8);
    buffer[offset++] = (byte)(PayloadLength);
}
else
{ // write in the header
    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | PayloadLength);
}
if (Mask.HasValue)
{
    int mask = Mask.Value;
    buffer[offset++] = (byte)(mask >> 24);
    buffer[offset++] = (byte)(mask >> 16);
    buffer[offset++] = (byte)(mask >> 8);
    buffer[offset++] = (byte)(mask);
}
// you might want to manually combine these into 1 packet
client.Send(buffer, 0, offset, SocketFlags.None);
client.Send(payload, 0, payload.Length, SocketFlags.None);

我可能应该注意到,
(byte)(expression)
转换只显式地使用最低有效字节,因此与
(byte)(expression&255)
完全相同。我真的不懂这些东西。我知道将数据从服务器移动到客户机需要序列化、加密、发送、接收、未加密和未序列化,但为什么它必须要用十六进制代码和垃圾代码如此复杂?我的问题是,我不理解协议的真正低级别,我不想,我只想让它工作,继续我的生活,而不必担心它会崩溃或以后效率低下,因为我选择了错误的第三方DLL。变量:PayloadLength、buffer、IsFinal、OpCode和Mask做什么,在代码运行之前,它们需要设置为什么?
PayloadLength
是我将要发送的消息的大小,以字节为单位;因此,如果我发送的是字符串消息,它是UTF-8编码的大块的长度
buffer
是一个
字节[]
,我正在使用一个临时缓冲区<如果您不知道它是什么,那么code>IsFinal可能应该是
true
。。。可以使用WebSocket在多个“框架”上拆分单个消息;这控制了它的工作方式<代码>操作代码对于文本消息是
1
,对于二进制消息是
2
,对于结束是
8
,对于继续是
0
,对于ping是
9
,对于pong是
10
<代码>面具是安全的东西;既然您是在和客户机交谈,它基本上应该是
int?掩码=空
使代码“按原样”工作,因为服务器从不使用掩码(客户端总是使用掩码);那么,@Jrud?已经编辑了我的答案,请重新编辑
bytesFormatted[0] = 129

indexStartRawData = -1 // don't matter what value is here; it will be set now:

if bytesRaw.length <= 125
    bytesFormatted[1] = bytesRaw.length

    indexStartRawData = 2

else if bytesRaw.length >= 126 and bytesRaw.length <= 65535
    bytesFormatted[1] = 126
    bytesFormatted[2] = ( bytesRaw.length >> 8 ) AND 255
    bytesFormatted[3] = ( bytesRaw.length      ) AND 255

    indexStartRawData = 4

else
    bytesFormatted[1] = 127
    bytesFormatted[2] = ( bytesRaw.length >> 56 ) AND 255
    bytesFormatted[3] = ( bytesRaw.length >> 48 ) AND 255
    bytesFormatted[4] = ( bytesRaw.length >> 40 ) AND 255
    bytesFormatted[5] = ( bytesRaw.length >> 32 ) AND 255
    bytesFormatted[6] = ( bytesRaw.length >> 24 ) AND 255
    bytesFormatted[7] = ( bytesRaw.length >> 16 ) AND 255
    bytesFormatted[8] = ( bytesRaw.length >>  8 ) AND 255
    bytesFormatted[9] = ( bytesRaw.length       ) AND 255

    indexStartRawData = 10

// put raw data at the correct index
bytesFormatted.put(bytesRaw, indexStartRawData)


// now send bytesFormatted (e.g. write it to the socket stream)
private static void SendMessage(string Msg, Socket client, int WebSockVersion)
        {
            if (WebSockVersion >= 8)
            {
                bool IsFinal = true;
                int OpCode = 1;
                int? Mask = null;
                int PayloadLength = Encoding.UTF8.GetBytes(Msg).Length;
                byte[] buffer = Encoding.UTF8.GetBytes(Msg);

                int offset = 0;
                buffer[offset++] = (byte)((IsFinal ? 128 : 0) | ((int)OpCode & 15));
                if (PayloadLength > ushort.MaxValue)
                { // write as a 64-bit length
                    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | 127);
                    buffer[offset++] = 0;
                    buffer[offset++] = 0;
                    buffer[offset++] = 0;
                    buffer[offset++] = 0;
                    buffer[offset++] = (byte)(PayloadLength >> 24);
                    buffer[offset++] = (byte)(PayloadLength >> 16);
                    buffer[offset++] = (byte)(PayloadLength >> 8);
                    buffer[offset++] = (byte)(PayloadLength);
                }
                else if (PayloadLength > 125)
                { // write as a 16-bit length
                    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | 126);
                    buffer[offset++] = (byte)(PayloadLength >> 8);
                    buffer[offset++] = (byte)(PayloadLength);
                }
                else
                { // write in the header
                    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | PayloadLength);
                }
                if (Mask.HasValue)
                {
                    int mask = Mask.Value;
                    buffer[offset++] = (byte)(mask >> 24);
                    buffer[offset++] = (byte)(mask >> 16);
                    buffer[offset++] = (byte)(mask >> 8);
                    buffer[offset++] = (byte)(mask);
                }
                //stream.Write(buffer, 0, offset);

                client.Send(buffer, 0, PayloadLength, SocketFlags.None);

            }
            else 
            {
                client.Send(new byte[] { 0x00 });
                client.Send(Encoding.UTF8.GetBytes(Msg));
                client.Send(new byte[] { 0xFF });
            }
        }
int offset = 0;
buffer[offset++] = (byte)((IsFinal ? 128 : 0) | ((int)OpCode & 15));
if (PayloadLength > ushort.MaxValue)
{ // write as a 64-bit length
    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | 127);
    buffer[offset++] = 0;
    buffer[offset++] = 0;
    buffer[offset++] = 0;
    buffer[offset++] = 0;
    buffer[offset++] = (byte)(PayloadLength >> 24);
    buffer[offset++] = (byte)(PayloadLength >> 16);
    buffer[offset++] = (byte)(PayloadLength >> 8);
    buffer[offset++] = (byte)(PayloadLength);
}
else if (PayloadLength > 125)
{ // write as a 16-bit length
    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | 126);
    buffer[offset++] = (byte)(PayloadLength >> 8);
    buffer[offset++] = (byte)(PayloadLength);
}
else
{ // write in the header
    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | PayloadLength);
}
if (Mask.HasValue)
{
    int mask = Mask.Value;
    buffer[offset++] = (byte)(mask >> 24);
    buffer[offset++] = (byte)(mask >> 16);
    buffer[offset++] = (byte)(mask >> 8);
    buffer[offset++] = (byte)(mask);
}
stream.Write(buffer, 0, offset);
bool IsFinal = true;
int OpCode = 1;
int? Mask = null;
byte[] payload = Encoding.UTF8.GetBytes(Msg);
int PayloadLength = payload.Length;
byte[] buffer = new byte[64]; // for working out the header

int offset = 0;
buffer[offset++] = (byte)((IsFinal ? 128 : 0) | ((int)OpCode & 15));
if (PayloadLength > ushort.MaxValue)
{ // write as a 64-bit length
    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | 127);
    buffer[offset++] = 0;
    buffer[offset++] = 0;
    buffer[offset++] = 0;
    buffer[offset++] = 0;
    buffer[offset++] = (byte)(PayloadLength >> 24);
    buffer[offset++] = (byte)(PayloadLength >> 16);
    buffer[offset++] = (byte)(PayloadLength >> 8);
    buffer[offset++] = (byte)(PayloadLength);
}
else if (PayloadLength > 125)
{ // write as a 16-bit length
    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | 126);
    buffer[offset++] = (byte)(PayloadLength >> 8);
    buffer[offset++] = (byte)(PayloadLength);
}
else
{ // write in the header
    buffer[offset++] = (byte)((Mask.HasValue ? 128 : 0) | PayloadLength);
}
if (Mask.HasValue)
{
    int mask = Mask.Value;
    buffer[offset++] = (byte)(mask >> 24);
    buffer[offset++] = (byte)(mask >> 16);
    buffer[offset++] = (byte)(mask >> 8);
    buffer[offset++] = (byte)(mask);
}
// you might want to manually combine these into 1 packet
client.Send(buffer, 0, offset, SocketFlags.None);
client.Send(payload, 0, payload.Length, SocketFlags.None);