websocket与C# socket相互通信

这篇具有很好参考价值的文章主要介绍了websocket与C# socket相互通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

web端代码就是js代码,C#有两种方式:使用第三方库,如Fleck,使用C#原生socket编程实现
 
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>
 
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();
                    }
                }
            }
        }

    }
}

 文章来源地址https://www.toymoban.com/news/detail-422537.html

websocket关闭机制
通信双方都可以主动关闭连接,不管谁关闭连接,对方都能收到消息。
client端关闭连接,server端能收到内容长度为0的消息。
server端关闭连接,client端会触发onclose事件。
 

到了这里,关于websocket与C# socket相互通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C# Socket通信从入门到精通(15)——单个同步UDP服务器监听一个客户端C#代码实现

    我们在开发UDP通信程序时,除了开发UDP客户端程序,有时候我们也需要开发UDP服务器程序,这在实际项目中是经常会遇到的,所以说掌握UDP服务器程序的开发是一项必备的技能,尤其在上位机软件开发领域,掌握UDP服务器程序的开发是走向高级工程师的必经之路,也是面试必

    2024年02月03日
    浏览(60)
  • 如何实现前端实时通信(WebSocket、Socket.io等)?

    聚沙成塔·每天进步一点点 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发者,这里都将为你提供一个系统而

    2024年01月22日
    浏览(48)
  • 两种实现WebSocket的方式,基于Java实现WebSocket。

    首先我们声明WebSocker方便打字为ws。 WebSocker ws = new WebSocket(); 或者说启用spring框架,因为spring已经整合了ws。 配置类:把spring中的ServerEndpointEx porter对象注入进来 用iava注解来 @ServerEndpoint          监听连接、 @OnOpen          连接成功、 @OnClose        连接关闭、 @

    2024年01月21日
    浏览(46)
  • Python中两种网络编程方式:Socket和HTTP协议

    本文分享自华为云社区《Python网络编程实践从Socket到HTTP协议的探索与实现》,作者:柠檬味拥抱。 在当今互联网时代,网络编程是程序员不可或缺的一项技能。Python作为一种高级编程语言,提供了丰富的网络编程库,使得开发者能够轻松地实现各种网络应用。本文将介绍P

    2024年04月16日
    浏览(42)
  • SpringBoot集成WebSocket的两种方式

    本站在2014年4月时曾全面的学习HTML5的技术,特写过HTML5的WebSocket示例,当时使用的Servlet3.0规范中的API,需要Tomcat7的支持(貌似在Tomcat6的后期维护版本也增加了WebSocket的支持),早在当初该示例还是本站的一个特色功能,好多来找我要源码的呢。时隔多年再来使用SpringBoot架构

    2024年02月15日
    浏览(58)
  • SpringBoot项目整合WebSocket+netty实现前后端双向通信(同时支持前端webSocket和socket协议哦)

    目录   前言 技术栈 功能展示 一、springboot项目添加netty依赖 二、netty服务端 三、netty客户端 四、测试 五、代码仓库地址   专属小彩蛋:前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站(前言 - 床长人工智能教程

    2024年02月12日
    浏览(50)
  • 远程服务和web服务和前端,三方通过socket和websocket进行双向通信传输数据

    1. 什么是socket? 在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。 2. 什么是websocket? WebSocket是一种网络通信协议,是HTML5新增的特性,

    2024年02月15日
    浏览(58)
  • websocket实时通讯和socket.io实时通信库的使用;心跳机制与断线重连

    https://zh.javascript.info/websocket WebSocket 是一种网络通信协议,就类似于 HTTP 也是一种通信协议。 为什么需要 WebSocket? 因为 HTTP 协议有一个缺陷:通信只能由客户端发起。 代码解析: 创建WebSocket实例:通过 new WebSocket() 创建一个WebSocket实例。在括号中传入服务器的URL,该URL指定了

    2024年02月16日
    浏览(42)
  • 【Unity】Socket网络通信(TCP) - 最基础的C#服务端通信流程

    我这里新建了一个C#控制台项目来写服务端代码。 下面是基于C# Socket的最基础服务端通信流程: 创建服务端Socket对象 绑定IP地址和端口 设置最大监听客户端数量 等待客户端连接 收发消息 释放连接 基于上面流程就能实现一个最简单并且能和客户端通信的服务器程序,每个步

    2023年04月16日
    浏览(64)
  • C# socket——简单的TCP 客户端 连接通信

    TCP编程的客户端一般步骤是: 1、创建一个socket,用函数socket()。 2、设置socket属性。 3、设置要连接的对方的IP地址和端口等属性。 4、连接服务器,用函数connect()。 5、收发数据,用函数send()和recv(),或者read()和write()。 6、关闭网络连接。 using System; using System.Net; using System.

    2024年02月11日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包