翼度科技»论坛 编程开发 .net 查看内容

websocket与C# socket相互通信

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
web端代码就是js代码,C#有两种方式:使用第三方库,如Fleck,使用C#原生socket编程实现 web端:
  1. <!doctype html>
  2. <html lang="zh-CN">
  3.     <head>
  4.         <meta charset="UTF-8">
  5.         <title>下发网站上文件到学生机</title>
  6.         
  7.     </head>
  8.     <body>
  9.         
  10.             <table border="1" cellspacing="0">
  11.                 <tr>
  12.                     <th>试卷号</th>
  13.                     <th>试卷名称</th>
  14.                     <th>描述</th>
  15.                     <th>操作</th>
  16.                 </tr>
  17.                 <tr>
  18.                     <td>JCLX01</td>
  19.                     <td>基础练习一</td>
  20.                     <td>建账、会计期间设置、部门职员设置、银行账户设置、科目设置等</td>
  21.                     <td><button id="btnDownload" onclick="callDesktopReceiveFile(this)">下发</button></td>
  22.                 </tr>
  23.                 <tr>
  24.                     <td>JCLX02</td>
  25.                     <td>基础练习二</td>
  26.                     <td>建账、会计期间设置、部门职员设置、银行账户设置、科目设置等</td>
  27.                     <td><button id="btnDownload" onclick="callDesktopReceiveFile(this)">下发</button></td>
  28.                 </tr>
  29.             </table>
  30.             
  31.         
  32.     </body>
  33. </html>
复制代码
 C#端方式一:使用第三方库Fleck参考:http://chanpinxue.cn/archives/979.html 方式二:使用C#原生socket编程自行实现
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.Threading;
  10. using U8FileTransfer.TcpHelper;
  11. using System.Net.Sockets;
  12. using System.Net;
  13. using System.Security.Cryptography;
  14. namespace CodeExperiment
  15. {
  16.     public partial class Form1 : Form
  17.     {
  18.         public Form1()
  19.         {
  20.             InitializeComponent();
  21.             Thread thread = new Thread(websocketListen);
  22.             thread.IsBackground = true;
  23.             thread.Start();
  24.             
  25.         }
  26.         /// <summary>
  27.         /// 解析客户端数据包,防止乱码
  28.         /// </summary>
  29.         /// <param name="recBytes">服务器接收的数据包</param>
  30.         /// <param name="recByteLength">有效数据长度</param>
  31.         /// <returns></returns>
  32.         private static string AnalyticData(byte[] recBytes, int recByteLength)
  33.         {
  34.             if (recByteLength < 2) { return string.Empty; }
  35.             bool fin = (recBytes[0] & 0x80) == 0x80; // 1bit,1表示最后一帧  
  36.             if (!fin)
  37.             {
  38.                 return string.Empty;// 超过一帧暂不处理
  39.             }
  40.             bool mask_flag = (recBytes[1] & 0x80) == 0x80; // 是否包含掩码  
  41.             if (!mask_flag)
  42.             {
  43.                 return string.Empty;// 不包含掩码的暂不处理
  44.             }
  45.             int payload_len = recBytes[1] & 0x7F; // 数据长度  
  46.             byte[] masks = new byte[4];
  47.             byte[] payload_data;
  48.             if (payload_len == 126)
  49.             {
  50.                 Array.Copy(recBytes, 4, masks, 0, 4);
  51.                 payload_len = (UInt16)(recBytes[2] << 8 | recBytes[3]);
  52.                 payload_data = new byte[payload_len];
  53.                 Array.Copy(recBytes, 8, payload_data, 0, payload_len);
  54.             }
  55.             else if (payload_len == 127)
  56.             {
  57.                 Array.Copy(recBytes, 10, masks, 0, 4);
  58.                 byte[] uInt64Bytes = new byte[8];
  59.                 for (int i = 0; i < 8; i++)
  60.                 {
  61.                     uInt64Bytes[i] = recBytes[9 - i];
  62.                 }
  63.                 UInt64 len = BitConverter.ToUInt64(uInt64Bytes, 0);
  64.                 payload_data = new byte[len];
  65.                 for (UInt64 i = 0; i < len; i++)
  66.                 {
  67.                     payload_data[i] = recBytes[i + 14];
  68.                 }
  69.             }
  70.             else
  71.             {
  72.                 Array.Copy(recBytes, 2, masks, 0, 4);
  73.                 payload_data = new byte[payload_len];
  74.                 Array.Copy(recBytes, 6, payload_data, 0, payload_len);
  75.             }
  76.             for (var i = 0; i < payload_len; i++)
  77.             {
  78.                 payload_data[i] = (byte)(payload_data[i] ^ masks[i % 4]);
  79.             }
  80.             return Encoding.UTF8.GetString(payload_data);
  81.         }
  82.         /// <summary>
  83.         /// 打包服务器数据,防止乱码
  84.         /// </summary>
  85.         /// <param name="message">数据</param>
  86.         /// <returns>数据包</returns>
  87.         private static byte[] PackData(string message)
  88.         {
  89.             byte[] contentBytes = null;
  90.             byte[] temp = Encoding.UTF8.GetBytes(message);
  91.             if (temp.Length < 126)
  92.             {
  93.                 contentBytes = new byte[temp.Length + 2];
  94.                 contentBytes[0] = 0x81;
  95.                 contentBytes[1] = (byte)temp.Length;
  96.                 Array.Copy(temp, 0, contentBytes, 2, temp.Length);
  97.             }
  98.             else if (temp.Length < 0xFFFF)
  99.             {
  100.                 contentBytes = new byte[temp.Length + 4];
  101.                 contentBytes[0] = 0x81;
  102.                 contentBytes[1] = 126;
  103.                 contentBytes[2] = (byte)(temp.Length & 0xFF);
  104.                 contentBytes[3] = (byte)(temp.Length >> 8 & 0xFF);
  105.                 Array.Copy(temp, 0, contentBytes, 4, temp.Length);
  106.             }
  107.             else
  108.             {
  109.                 // 暂不处理超长内容  
  110.             }
  111.             return contentBytes;
  112.         }
  113.         /// <summary>
  114.         /// 客户端消息结构化
  115.         /// message参数格式为多个key:value键值对通过分号拼接组成,示例:
  116.         /// content:download_and_send;file-url:https://www.a.com/a.zip;
  117.         ///
  118.         /// </summary>
  119.         /// <param name="message"></param>
  120.         /// <returns></returns>
  121.         private Dictionary<string, string> ProcessRemoteMessage(string message)
  122.         {
  123.             Dictionary<string, string> dic = new Dictionary<string, string>();
  124.             if (message.Substring(message.Length - 1, 1) == ";")
  125.             {
  126.                 message = message.Substring(0, message.Length - 1);
  127.             }
  128.             string[] strs = message.Split(';');
  129.             if (strs.Length > 0)
  130.             {
  131.                 Console.WriteLine("- - - - - - - - - - - - - - - - - - -");
  132.                 foreach (string s in strs)
  133.                 {
  134.                     Console.WriteLine(s);
  135.                     string[] split = s.Split(new char[] { ':' }, 2);
  136.                     Console.WriteLine("[" + split[0] + "][" + split[1] + "]");
  137.                     dic.Add(split[0], split[1]);
  138.                 }
  139.                 Console.WriteLine("- - - - - - - - - - - - - - - - - - -");
  140.             }
  141.             return dic;
  142.         }
  143.         private void websocketListen()
  144.         {
  145.             Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  146.             EndPoint endPoint = new IPEndPoint(IPAddress.Any, 14567);//监听端口
  147.             server.Bind(endPoint);
  148.             server.Listen(10); // 排队等待连接最大数量10
  149.             // 监听多个客户端连接
  150.             while (true)
  151.             {
  152.                 Socket client = server.Accept();
  153.                 Console.WriteLine("有客户端连上来了");
  154.                 //接收客户端发来的HTTP-Header消息
  155.                 byte[] bytes = new byte[1024];
  156.                 int len = client.Receive(bytes);
  157.                 string strMessage = Encoding.UTF8.GetString(bytes, 0, len);
  158.                 Console.WriteLine(strMessage);
  159.                 //获取Sec-WebSocket-Key,为握手做准备
  160.                 string[] strings = strMessage.Split('\n');
  161.                 string strSecWebSocketKey = "";
  162.                 foreach (var item in strings)
  163.                 {
  164.                     string[] strings1 = item.Split(':');
  165.                     if (strings1[0] == "Sec-WebSocket-Key")
  166.                     {
  167.                         strSecWebSocketKey = strings1[1].Trim();
  168.                     }
  169.                 }
  170.                 //生成服务端Sec-WebSocket-Accept,迎合客户端的握手请求
  171.                 byte[] secKeyBytes = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(strSecWebSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
  172.                 string secKey = Convert.ToBase64String(secKeyBytes);
  173.                 // 发送给客户端完成握手(会触发Websocket的open()回调函数),针对websocket必须使用以下header
  174.                 string strHeader = "";
  175.                 strHeader += "HTTP/1.1 101 Switching Protocols" + Environment.NewLine;
  176.                 strHeader += "Upgrade: websocket" + Environment.NewLine;
  177.                 strHeader += "Connection: Upgrade" + Environment.NewLine;
  178.                 strHeader += "Sec-WebSocket-Accept: " + secKey + Environment.NewLine + Environment.NewLine;
  179.                 client.Send(Encoding.UTF8.GetBytes(strHeader));
  180.                 string remoteFileUrl = null;
  181.                 bool clientClose = false;
  182.                 // 循环接收websocket发来的消息实现双方交流
  183.                 while (!clientClose)
  184.                 {
  185.                     //接收客户端发来的消息
  186.                     byte[] bytes2 = new byte[1024];
  187.                     int len2 = client.Receive(bytes2);
  188.                     string strMessage2 = AnalyticData(bytes2, len2);
  189.                     if (strMessage2.Length > 0)
  190.                     {
  191.                         Console.WriteLine("客户端发来消息:{0}", strMessage2);
  192.                         Dictionary<string, string> messageDic = ProcessRemoteMessage(strMessage2);
  193.                         string content = null;
  194.                         messageDic.TryGetValue("content", out content);
  195.                         Console.WriteLine("message content:" + content);
  196.                         if (content == "receiveFile")
  197.                         {
  198.                             messageDic.TryGetValue("url", out remoteFileUrl);
  199.                             client.Send(PackData("roger"));
  200.                             Console.WriteLine("remoteFileUrl: " + remoteFileUrl);
  201.                             Console.WriteLine("to do invoke download.");
  202.                             // 关闭连接
  203.                             client.Shutdown(SocketShutdown.Both);
  204.                             client.Close();
  205.                             clientClose = true;
  206.                         }
  207.                     }
  208.                     else
  209.                     {
  210.                         Console.WriteLine("客户端关闭了连接");
  211.                         client.Shutdown(SocketShutdown.Both);
  212.                         client.Close();
  213.                     }
  214.                 }
  215.             }
  216.         }
  217.     }
  218. }
复制代码
 
websocket关闭机制通信双方都可以主动关闭连接,不管谁关闭连接,对方都能收到消息。client端关闭连接,server端能收到内容长度为0的消息。server端关闭连接,client端会触发onclose事件。 
来源:https://www.cnblogs.com/jsper/archive/2023/04/23/17346323.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具