websocket C# server


  1. ---客户端
    1. <!DOCTYPE html>  
    2. <html>  
    3. <head>  
    4.     <title></title>  
    5.     <script type="text/javascript">  
    6.         var ws;  
    7.         function ToggleConnectionClicked() {  
    8.             try {  
    9.                 var SOCKECT_ADDR = "ws://localhost:1818/chat";  
    10.                 ws = new WebSocket(SOCKECT_ADDR);     
    11.   
    12.                 ws.onopen = function (event) { alert("已经与服务器建立了连接\r\n当前连接状态:" + this.readyState); };  
    13.                 ws.onmessage = function (event) { alert("接收到服务器发送的数据:\r\n" + event.data); };  
    14.                 ws.onclose = function (event) { alert("已经与服务器断开连接\r\n当前连接状态:" + this.readyState); };  
    15.                 ws.onerror = function (event) {alert("WebSocket异常!" + event.toString());};  
    16.             } catch (ex) {  
    17.                 alert(ex.message);  
    18.             }  
    19.         };  
    20.   
    21.         function SendData() {  
    22.             try {  
    23.                 ws.send("success");  
    24.             } catch (ex) {  
    25.                 alert(ex.message);  
    26.             }  
    27.         };  
    28.   
    29.         function seestate() {  
    30.             alert(ws.readyState);  
    31.         }  
    32.          
    33.     </script>  
    34. </head>  
    35. <body>  
    36.     <button id='ToggleConnection' type="button" onclick='ToggleConnectionClicked();'>  
    37.         连接服务器</button><br />  
    38.     <br />  
    39.     <button id='ToggleConnection' type="button" onclick='SendData();'>  
    40.         发送我的名字:beston</button><br />  
    41.     <br />  
    42.     <button id='ToggleConnection' type="button" onclick='seestate();'>  
    43.         查看状态</button><br />  
    44.     <br />  
    45. </body>  
    46. </html> 
     



----------------------------------服务端
  1. using System;  
  2. using System.Text;  
  3. using System.Net;  
  4. using System.Net.Sockets;  
  5. using System.Text.RegularExpressions;  
  6. using System.Security.Cryptography;  
  7.   
  8. namespace WebSocketServer  
  9. {  
  10.     class Program  
  11.     {  
  12.         static string byte_to_string(byte[] b)  
  13.         {  
  14.             string s = "";  
  15.             foreach(byte _b in b)  
  16.             {  
  17.                 s += _b.ToString();  
  18.             }  
  19.             return s;  
  20.         }  
  21.         static void Main(string[] args)  
  22.         {  
  23.             int port = 1818;  
  24.             byte[] buffer = new byte[1024];  
  25.   
  26.             IPEndPoint localEP = new IPEndPoint(IPAddress.Any, port);  
  27.             Socket listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);  
  28.   
  29.             try  
  30.             {  
  31.                 listener.Bind(localEP);  
  32.                 listener.Listen(10);  
  33.   
  34.                 Console.WriteLine("等待客户端连接....");  
  35.                 Socket sc = listener.Accept();//接受一个连接  
  36.                 Console.WriteLine("接受到了客户端:" + sc.RemoteEndPoint.ToString() + "连接....");  
  37.   
  38.                 //握手  
  39.                 int length = sc.Receive(buffer);//接受客户端握手信息  
  40.                 sc.Send(PackHandShakeData(GetSecKeyAccetp(buffer, length)));  
  41.                 Console.WriteLine("已经发送握手协议了....");  
  42.   
  43.                 //接受客户端数据  
  44.                 Console.WriteLine("等待客户端数据....");  
  45.                 length = sc.Receive(buffer);//接受客户端信息  
  46.                 string clientMsg = AnalyticData(buffer, length);  
  47.                 Console.WriteLine("接受到客户端数据:" + clientMsg);  
  48.   
  49.                 //发送数据  
  50.                 string sendMsg = "您好," + clientMsg;  
  51.                 Console.WriteLine("发送数据:“" + sendMsg + "” 至客户端....");  
  52.                 sc.Send(PackData(sendMsg));  
  53.   
  54.                 Console.WriteLine("演示Over!");  
  55.                 Console.Read();  
  56.             }  
  57.             catch (Exception e)  
  58.             {  
  59.                 Console.WriteLine(e.ToString());  
  60.             }  
  61.   
  62.         }  
  63.   
  64.         /// <summary>  
  65.         /// 打包握手信息  
  66.         /// </summary>  
  67.         /// <param name="secKeyAccept">Sec-WebSocket-Accept</param>  
  68.         /// <returns>数据包</returns>  
  69.         private static byte[] PackHandShakeData(string secKeyAccept)  
  70.         {  
  71.             var responseBuilder = new StringBuilder();  
  72.             responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + Environment.NewLine);  
  73.             responseBuilder.Append("Upgrade: websocket" + Environment.NewLine);  
  74.             responseBuilder.Append("Connection: Upgrade" + Environment.NewLine);  
  75.             responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine + Environment.NewLine);  
  76.             return Encoding.UTF8.GetBytes(responseBuilder.ToString());  
  77.         }  
  78.   
  79.         /// <summary>  
  80.         /// 生成Sec-WebSocket-Accept  
  81.         /// </summary>  
  82.         /// <param name="handShakeText">客户端握手信息</param>  
  83.         /// <returns>Sec-WebSocket-Accept</returns>  
  84.         private static string GetSecKeyAccetp(byte[] handShakeBytes, int bytesLength)  
  85.         {  
  86.             string handShakeText = Encoding.UTF8.GetString(handShakeBytes, 0, bytesLength);  
  87.             string key = string.Empty;  
  88.             Regex r = new Regex(@"Sec\-WebSocket\-Key:(.*?)\r\n");  
  89.             Match m = r.Match(handShakeText);  
  90.             if (m.Groups.Count != 0)  
  91.             {  
  92.                 key = Regex.Replace(m.Value, @"Sec\-WebSocket\-Key:(.*?)\r\n""$1").Trim();  
  93.             }  
  94.             byte[] encryptionString = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));  
  95.             return Convert.ToBase64String(encryptionString);  
  96.         }  
  97.   
  98.         /// <summary>  
  99.         /// 解析客户端数据包  
  100.         /// </summary>  
  101.         /// <param name="recBytes">服务器接收的数据包</param>  
  102.         /// <param name="recByteLength">有效数据长度</param>  
  103.         /// <returns></returns>  
  104.         private static string AnalyticData(byte[] recBytes, int recByteLength)  
  105.         {  
  106.             if (recByteLength < 2) { return string.Empty; }  
  107.   
  108.             bool fin = (recBytes[0] & 0x80) == 0x80; // 1bit,1表示最后一帧    
  109.             if (!fin)  
  110.             {  
  111.                 return string.Empty;// 超过一帧暂不处理   
  112.             }  
  113.   
  114.             bool mask_flag = (recBytes[1] & 0x80) == 0x80; // 是否包含掩码    
  115.             if (!mask_flag)  
  116.             {  
  117.                 return string.Empty;// 不包含掩码的暂不处理  
  118.             }  
  119.   
  120.             int payload_len = recBytes[1] & 0x7F; // 数据长度    
  121.   
  122.             byte[] masks = new byte[4];  
  123.             byte[] payload_data;  
  124.   
  125.             if (payload_len == 126)  
  126.             {  
  127.                 Array.Copy(recBytes, 4, masks, 0, 4);  
  128.                 payload_len = (UInt16)(recBytes[2] << 8 | recBytes[3]);  
  129.                 payload_data = new byte[payload_len];  
  130.                 Array.Copy(recBytes, 8, payload_data, 0, payload_len);  
  131.   
  132.             }  
  133.             else if (payload_len == 127)  
  134.             {  
  135.                 Array.Copy(recBytes, 10, masks, 0, 4);  
  136.                 byte[] uInt64Bytes = new byte[8];  
  137.                 for (int i = 0; i < 8; i++)  
  138.                 {  
  139.                     uInt64Bytes[i] = recBytes[9 - i];  
  140.                 }  
  141.                 UInt64 len = BitConverter.ToUInt64(uInt64Bytes, 0);  
  142.   
  143.                 payload_data = new byte[len];  
  144.                 for (UInt64 i = 0; i < len; i++)  
  145.                 {  
  146.                     payload_data[i] = recBytes[i + 14];  
  147.                 }  
  148.             }  
  149.             else  
  150.             {  
  151.                 Array.Copy(recBytes, 2, masks, 0, 4);  
  152.                 payload_data = new byte[payload_len];  
  153.                 Array.Copy(recBytes, 6, payload_data, 0, payload_len);  
  154.   
  155.             }  
  156.   
  157.             for (var i = 0; i < payload_len; i++)  
  158.             {  
  159.                 payload_data[i] = (byte)(payload_data[i] ^ masks[i % 4]);  
  160.             }  
  161.   
  162.             return Encoding.UTF8.GetString(payload_data);  
  163.         }  
  164.   
  165.   
  166.         /// <summary>  
  167.         /// 打包服务器数据  
  168.         /// </summary>  
  169.         /// <param name="message">数据</param>  
  170.         /// <returns>数据包</returns>  
  171.         private static byte[] PackData(string message)  
  172.         {  
  173.             byte[] contentBytes = null;  
  174.             byte[] temp = Encoding.UTF8.GetBytes(message);  
  175.   
  176.             if (temp.Length < 126)  
  177.             {  
  178.                 contentBytes = new byte[temp.Length + 2];  
  179.                 contentBytes[0] = 0x81;  
  180.                 contentBytes[1] = (byte)temp.Length;  
  181.                 Array.Copy(temp, 0, contentBytes, 2, temp.Length);  
  182.             }  
  183.             else if (temp.Length < 0xFFFF)  
  184.             {  
  185.                 contentBytes = new byte[temp.Length + 4];  
  186.                 contentBytes[0] = 0x81;  
  187.                 contentBytes[1] = 126;  
  188.                 contentBytes[2] = (byte)(temp.Length & 0xFF);  
  189.                 contentBytes[3] = (byte)(temp.Length >> 8 & 0xFF);  
  190.                 Array.Copy(temp, 0, contentBytes, 4, temp.Length);  
  191.             }  
  192.             else  
  193.             {  
  194.                 // 暂不处理超长内容    
  195.             }  
  196.   
  197.             return contentBytes;  
  198.         }  
  199.   
  200.     }  
  201. }  




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值