Skip to main content
 首页 » 编程设计

c#之Websockets之断开服务器消息

2024年01月24日32insus

我是 Websockets 的新手,正在寻找使用 WS 和 c# 控制台应用程序的工作示例。 我遇到了 this one ,但我已经有问题了。当服务器向客户端发送消息时,连接似乎已关闭。我不确定,但我认为握手没问题。这是一个代码:

服务器:

using System; 
using System.Net.Sockets; 
using System.Net; 
using System.Security.Cryptography; 
using System.Threading; 
 
namespace ConsoleApplication1 
{ 
    class Program 
    { 
        static Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 
        static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; 
 
        static void Main(string[] args) 
        { 
            serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080)); 
            serverSocket.Listen(128); 
            serverSocket.BeginAccept(null, 0, OnAccept, null); 
            Console.Read(); 
        } 
 
        private static void OnAccept(IAsyncResult result) 
        { 
            byte[] buffer = new byte[1024]; 
            try 
            { 
                Socket client = null; 
                string headerResponse = ""; 
                if (serverSocket != null && serverSocket.IsBound) 
                { 
                    client = serverSocket.EndAccept(result); 
                    var i = client.Receive(buffer); 
                    headerResponse = (System.Text.Encoding.UTF8.GetString(buffer)).Substring(0, i); 
                    // write received data to the console 
                    Console.WriteLine(headerResponse); 
                    Console.WriteLine("====================="); 
                } 
                if (client != null) 
                { 
                    /* Handshaking and managing ClientSocket */ 
 
                    var key = headerResponse.Replace("ey:", "`") 
                              .Split('`')[1]                     // dGhlIHNhbXBsZSBub25jZQ== \r\n ....... 
                              .Replace("\r", "").Split('\n')[0]  // dGhlIHNhbXBsZSBub25jZQ== 
                              .Trim(); 
 
                    // key should now equal dGhlIHNhbXBsZSBub25jZQ== 
                    var test1 = AcceptKey(ref key); 
 
                    var newLine = "\r\n"; 
 
                    var response = "HTTP/1.1 101 Switching Protocols" + newLine 
                         + "Upgrade: websocket" + newLine 
                         + "Connection: Upgrade" + newLine 
                         + "Sec-WebSocket-Accept: " + test1 + newLine + newLine 
                         //+ "Sec-WebSocket-Protocol: chat, superchat" + newLine 
                         //+ "Sec-WebSocket-Version: 13" + newLine 
                         ; 
 
                    // which one should I use? none of them fires the onopen method 
                    client.Send(System.Text.Encoding.UTF8.GetBytes(response)); 
 
                    var i = client.Receive(buffer); // wait for client to send a message 
 
                    // once the message is received decode it in different formats 
                    Console.WriteLine(Convert.ToBase64String(buffer).Substring(0, i)); 
                    Console.WriteLine("====================="); 
 
                    Console.WriteLine("\n\nPress enter to send data to client"); 
                    Console.Read(); 
 
                    var subA = SubArray<byte>(buffer, 0, i); 
                    client.Send(subA); 
 
                    Console.Read();                     
                    Thread.Sleep(10000);//wait for message to be send 
 
 
                } 
            } 
            catch (SocketException exception) 
            { 
                throw exception; 
            } 
            finally 
            { 
                if (serverSocket != null && serverSocket.IsBound) 
                { 
                    serverSocket.BeginAccept(null, 0, OnAccept, null); 
                } 
            } 
        } 
 
        public static T[] SubArray<T>(T[] data, int index, int length) 
        { 
            T[] result = new T[length]; 
            Array.Copy(data, index, result, 0, length); 
            return result; 
        } 
 
        private static string AcceptKey(ref string key) 
        { 
            string longKey = key + guid; 
            byte[] hashBytes = ComputeHash(longKey); 
            return Convert.ToBase64String(hashBytes); 
        } 
 
        static SHA1 sha1 = SHA1CryptoServiceProvider.Create(); 
        private static byte[] ComputeHash(string str) 
        { 
            return sha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(str)); 
        } 
    } 
} 

客户:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <script type="text/javascript"> 
        function connect() { 
            var ws = new WebSocket("ws://localhost:8080/service"); 
            ws.onopen = function () { 
                alert("About to send data"); 
                ws.send("Hello World"); // I WANT TO SEND THIS MESSAGE TO THE SERVER!!!!!!!! 
                alert("Message sent!"); 
            }; 
 
            ws.onmessage = function (evt) { 
                alert("About to receive data"); 
                var received_msg = evt.data; 
                alert("Message received = "+received_msg); 
            }; 
            ws.onclose = function () { 
                // websocket is closed. 
                alert("Connection is closed..."); 
            }; 
        }; 
 
 
    </script> 
</head> 
<body style="font-size:xx-large" > 
    <div> 
    <a href="#" onclick="connect()">Click here to start</a></div> 
</body> 
</html> 

这是来自客户端的连接请求和消息:

我们将不胜感激。

请您参考如下方法:

您不能只是“回显”您收到的缓冲区。 RFC 说,必须屏蔽从客户端到服务器的帧。它并没有说从服务器到客户端的消息一定不能,但至少对于 Chrome 来说不应该。 因此,如果你想回显数据,你必须解码(取消屏蔽)帧并构建一个新帧。有效负载需要与掩码 key 逐字节进行异或运算。

或者像这样发送数据:

byte[] send = new byte[3 + 2]; 
send[0] = 0x81; // last frame, text 
send[1] = 3; // not masked, length 3 
send[2] = 0x41; 
send[3] = 0x42; 
send[4] = 0x43; 
nwStream.Write(send, 0, send.Length); // nwStream = client.GetStream(), client is a TcpClient