web端代码就是js代码,C#有两种方式:使用第三方库,如Fleck,使用C#原生socket编程实现.
1、web端代码:
<!doctype html><html lang="zh-CN"><head><meta charset="UTF-8"><title>下发网站上文件到学生机</title><script type="text/javascript">function callDesktopReceiveFile(button) {var ws = null;if (button.innerHTML == '下发') {button.innerHTML = '取消';try {if (ws) ws.close();} catch(e) {console.log(e)}ws = new WebSocket('ws://127.0.0.1:14567');//监听是否连接成功ws.onopen = function () {console.log('ws连接状态[成功]:' + ws.readyState);ws.send("content:receiveFile;url:http://127.0.0.1:5500/2023CQGKMNT.dat;");// ws.close();console.log('发送消息');};// 接听服务器发回的信息并处理展示ws.onmessage = function (e) {console.log('接收到来自服务器的消息:' + e.data);// 如果服务器在业务上主动关闭连接,则此处无需再关闭// if (e.data === 'roger') {// ws.close();// }};// 监听连接关闭事件ws.onclose = function () {// 监听整个过程中websocket的状态console.log('ws连接状态[关闭]:' + ws.readyState);};// 监听并处理error事件ws.onerror = function (error) {console.log(error);};} else if (button.innerHTML == '取消') {try {if (ws) ws.close();} catch(e) {console.log(e)}button.innerHTML = '下发';}}</script></head><body><div><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></div></body></html>
2、C#端代码
方式一:使用第三方库Fleck
参考: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必须使用以下headerstring 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();}}}}}}