|
web端代码就是js代码,C#有两种方式:使用第三方库,如Fleck,使用C#原生socket编程实现 web端:- <!doctype html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <title>下发网站上文件到学生机</title>
-
- </head>
- <body>
-
- <table border="1" cellspacing="0">
- <tr>
- <th>试卷号</th>
- <th>试卷名称</th>
- <th>描述</th>
- <th>操作</th>
- </tr>
- <tr>
- <td>JCLX01</td>
- <td>基础练习一</td>
- <td>建账、会计期间设置、部门职员设置、银行账户设置、科目设置等</td>
- <td><button id="btnDownload" onclick="callDesktopReceiveFile(this)">下发</button></td>
- </tr>
- <tr>
- <td>JCLX02</td>
- <td>基础练习二</td>
- <td>建账、会计期间设置、部门职员设置、银行账户设置、科目设置等</td>
- <td><button id="btnDownload" onclick="callDesktopReceiveFile(this)">下发</button></td>
- </tr>
- </table>
-
-
- </body>
- </html>
复制代码 C#端方式一:使用第三方库Fleck参考:http://chanpinxue.cn/archives/979.html 方式二:使用C#原生socket编程自行实现- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- using System.Threading;
- using U8FileTransfer.TcpHelper;
- using System.Net.Sockets;
- using System.Net;
- using System.Security.Cryptography;
- namespace CodeExperiment
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- Thread thread = new Thread(websocketListen);
- thread.IsBackground = true;
- thread.Start();
-
- }
- /// <summary>
- /// 解析客户端数据包,防止乱码
- /// </summary>
- /// <param name="recBytes">服务器接收的数据包</param>
- /// <param name="recByteLength">有效数据长度</param>
- /// <returns></returns>
- private static string AnalyticData(byte[] recBytes, int recByteLength)
- {
- if (recByteLength < 2) { return string.Empty; }
- bool fin = (recBytes[0] & 0x80) == 0x80; // 1bit,1表示最后一帧
- if (!fin)
- {
- return string.Empty;// 超过一帧暂不处理
- }
- bool mask_flag = (recBytes[1] & 0x80) == 0x80; // 是否包含掩码
- if (!mask_flag)
- {
- return string.Empty;// 不包含掩码的暂不处理
- }
- int payload_len = recBytes[1] & 0x7F; // 数据长度
- byte[] masks = new byte[4];
- byte[] payload_data;
- if (payload_len == 126)
- {
- Array.Copy(recBytes, 4, masks, 0, 4);
- payload_len = (UInt16)(recBytes[2] << 8 | recBytes[3]);
- payload_data = new byte[payload_len];
- Array.Copy(recBytes, 8, payload_data, 0, payload_len);
- }
- else if (payload_len == 127)
- {
- Array.Copy(recBytes, 10, masks, 0, 4);
- byte[] uInt64Bytes = new byte[8];
- for (int i = 0; i < 8; i++)
- {
- uInt64Bytes[i] = recBytes[9 - i];
- }
- UInt64 len = BitConverter.ToUInt64(uInt64Bytes, 0);
- payload_data = new byte[len];
- for (UInt64 i = 0; i < len; i++)
- {
- payload_data[i] = recBytes[i + 14];
- }
- }
- else
- {
- Array.Copy(recBytes, 2, masks, 0, 4);
- payload_data = new byte[payload_len];
- Array.Copy(recBytes, 6, payload_data, 0, payload_len);
- }
- for (var i = 0; i < payload_len; i++)
- {
- payload_data[i] = (byte)(payload_data[i] ^ masks[i % 4]);
- }
- return Encoding.UTF8.GetString(payload_data);
- }
- /// <summary>
- /// 打包服务器数据,防止乱码
- /// </summary>
- /// <param name="message">数据</param>
- /// <returns>数据包</returns>
- private static byte[] PackData(string message)
- {
- byte[] contentBytes = null;
- byte[] temp = Encoding.UTF8.GetBytes(message);
- if (temp.Length < 126)
- {
- contentBytes = new byte[temp.Length + 2];
- contentBytes[0] = 0x81;
- contentBytes[1] = (byte)temp.Length;
- Array.Copy(temp, 0, contentBytes, 2, temp.Length);
- }
- else if (temp.Length < 0xFFFF)
- {
- contentBytes = new byte[temp.Length + 4];
- contentBytes[0] = 0x81;
- contentBytes[1] = 126;
- contentBytes[2] = (byte)(temp.Length & 0xFF);
- contentBytes[3] = (byte)(temp.Length >> 8 & 0xFF);
- Array.Copy(temp, 0, contentBytes, 4, temp.Length);
- }
- else
- {
- // 暂不处理超长内容
- }
- return contentBytes;
- }
- /// <summary>
- /// 客户端消息结构化
- /// message参数格式为多个key:value键值对通过分号拼接组成,示例:
- /// content:download_and_send;file-url:https://www.a.com/a.zip;
- ///
- /// </summary>
- /// <param name="message"></param>
- /// <returns></returns>
- private Dictionary<string, string> ProcessRemoteMessage(string message)
- {
- Dictionary<string, string> dic = new Dictionary<string, string>();
- if (message.Substring(message.Length - 1, 1) == ";")
- {
- message = message.Substring(0, message.Length - 1);
- }
- string[] strs = message.Split(';');
- if (strs.Length > 0)
- {
- Console.WriteLine("- - - - - - - - - - - - - - - - - - -");
- foreach (string s in strs)
- {
- Console.WriteLine(s);
- string[] split = s.Split(new char[] { ':' }, 2);
- Console.WriteLine("[" + split[0] + "][" + split[1] + "]");
- dic.Add(split[0], split[1]);
- }
- Console.WriteLine("- - - - - - - - - - - - - - - - - - -");
- }
- return dic;
- }
- private void websocketListen()
- {
- Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- EndPoint endPoint = new IPEndPoint(IPAddress.Any, 14567);//监听端口
- server.Bind(endPoint);
- server.Listen(10); // 排队等待连接最大数量10
- // 监听多个客户端连接
- while (true)
- {
- Socket client = server.Accept();
- Console.WriteLine("有客户端连上来了");
- //接收客户端发来的HTTP-Header消息
- byte[] bytes = new byte[1024];
- int len = client.Receive(bytes);
- string strMessage = Encoding.UTF8.GetString(bytes, 0, len);
- Console.WriteLine(strMessage);
- //获取Sec-WebSocket-Key,为握手做准备
- string[] strings = strMessage.Split('\n');
- string strSecWebSocketKey = "";
- foreach (var item in strings)
- {
- string[] strings1 = item.Split(':');
- if (strings1[0] == "Sec-WebSocket-Key")
- {
- strSecWebSocketKey = strings1[1].Trim();
- }
- }
- //生成服务端Sec-WebSocket-Accept,迎合客户端的握手请求
- byte[] secKeyBytes = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(strSecWebSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
- string secKey = Convert.ToBase64String(secKeyBytes);
- // 发送给客户端完成握手(会触发Websocket的open()回调函数),针对websocket必须使用以下header
- string strHeader = "";
- strHeader += "HTTP/1.1 101 Switching Protocols" + Environment.NewLine;
- strHeader += "Upgrade: websocket" + Environment.NewLine;
- strHeader += "Connection: Upgrade" + Environment.NewLine;
- strHeader += "Sec-WebSocket-Accept: " + secKey + Environment.NewLine + Environment.NewLine;
- client.Send(Encoding.UTF8.GetBytes(strHeader));
- string remoteFileUrl = null;
- bool clientClose = false;
- // 循环接收websocket发来的消息实现双方交流
- while (!clientClose)
- {
- //接收客户端发来的消息
- byte[] bytes2 = new byte[1024];
- int len2 = client.Receive(bytes2);
- string strMessage2 = AnalyticData(bytes2, len2);
- if (strMessage2.Length > 0)
- {
- Console.WriteLine("客户端发来消息:{0}", strMessage2);
- Dictionary<string, string> messageDic = ProcessRemoteMessage(strMessage2);
- string content = null;
- messageDic.TryGetValue("content", out content);
- Console.WriteLine("message content:" + content);
- if (content == "receiveFile")
- {
- messageDic.TryGetValue("url", out remoteFileUrl);
- client.Send(PackData("roger"));
- Console.WriteLine("remoteFileUrl: " + remoteFileUrl);
- Console.WriteLine("to do invoke download.");
- // 关闭连接
- client.Shutdown(SocketShutdown.Both);
- client.Close();
- clientClose = true;
- }
- }
- else
- {
- Console.WriteLine("客户端关闭了连接");
- client.Shutdown(SocketShutdown.Both);
- client.Close();
- }
- }
- }
- }
- }
- }
复制代码
websocket关闭机制通信双方都可以主动关闭连接,不管谁关闭连接,对方都能收到消息。client端关闭连接,server端能收到内容长度为0的消息。server端关闭连接,client端会触发onclose事件。
来源:https://www.cnblogs.com/jsper/archive/2023/04/23/17346323.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|