• Socket初见


    前端代码:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <title>WebSockets客户端示例</title>
    </head>
    <script>
        var webSocket;
        function connect() {
            try {
                var readyState = new Array("正在连接", "已建立连接", "正在关闭连接", "已关闭连接");
                var host = "ws://localhost:43423";
                webSocket = new WebSocket(host);
                var message = document.getElementById("message");
                message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
                webSocket.onopen = function () {
                    message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
                }
                webSocket.onmessage = function (msg) {
                    message.innerHTML += "<p>接收信息:" + msg.data + "</p>";
                }
                webSocket.onclose = function () {
                    message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
                }
            }
            catch (exception) {
                message.innerHTML += "<p>有错误发生</p>";
            }
        }
        function send() {
            var text = document.getElementById("text").value;
            var message = document.getElementById("message");
            if (text == "") {
                message.innerHTML += "<p>请输入一些文字</p>";
                return;
            }
            try {
                webSocket.send(text);
                message.innerHTML += "<p>发送数据:" + text + "</p>";
            }
            catch (exception) {
                message.innerHTML += "<p>发送数据出错</p>";
            }
            document.getElementById("text").value = "";
        }
        function disconnect() {
            webSocket.close();
        }
    </script>
    <body>
    <h1>WebSocket客户端示例</h1>
    <div id="message"></div>
    <p>请输入一些文字</p>
    <input id="text" type="text">
    <button id="connect" onClick="connect();">建立连接</button>
    <button id="send" onClick="send();">发送数据</button>
    <button id="disconnect" onClick="disconnect();">断开连接</button>
    </body>
    </html>

    后端代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;
    using System.Net;
    using System.Text.RegularExpressions;
    using System.Security.Cryptography;
    namespace WebSocket
    {
        class Program
        {
            static void Main(string[] args)
            {
                int port = 10;
                byte[] buffer = new byte[1024];
    
                IPEndPoint localEP = new IPEndPoint(IPAddress.Any, port);
                Socket listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    
                try
                {
                    listener.Bind(localEP);
                    listener.Listen(10);
    
                    Console.WriteLine("等待客户端连接....");
                    Socket sc = listener.Accept();//接受一个连接
                    Console.WriteLine("接受到了客户端:" + sc.RemoteEndPoint.ToString() + "连接....");
    
                    //握手
                    int length = sc.Receive(buffer);//接受客户端握手信息
                    sc.Send(PackHandShakeData(GetSecKeyAccetp(buffer, length)));
                    Console.WriteLine("已经发送握手协议了....");
    
                    //接受客户端数据
                    Console.WriteLine("等待客户端数据....");
                    length = sc.Receive(buffer);//接受客户端信息
                    string clientMsg = AnalyticData(buffer, length);
                    Console.WriteLine("接受到客户端数据:" + clientMsg);
    
                    //发送数据
                    string sendMsg = "您好," + clientMsg;
                    Console.WriteLine("发送数据:“" + sendMsg + "” 至客户端....");
                    sc.Send(PackData(sendMsg));
    
                    Console.WriteLine("演示Over!");
    
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
            /// <summary>
            /// 打包握手信息
            /// </summary>
            /// <param name="secKeyAccept"></param>
            /// <returns></returns>
            private static byte[] PackHandShakeData(string secKeyAccept)
            {
                var responseBuilder = new StringBuilder();
                responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + Environment.NewLine);
                responseBuilder.Append("Upgrade: websocket" + Environment.NewLine);
                responseBuilder.Append("Connection: Upgrade" + Environment.NewLine);
                responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine + Environment.NewLine);
                //如果把上一行换成下面两行,才是thewebsocketprotocol-17协议,但居然握手不成功,目前仍没弄明白!
                //responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine);
                //responseBuilder.Append("Sec-WebSocket-Protocol: chat" + Environment.NewLine);
    
                return Encoding.UTF8.GetBytes(responseBuilder.ToString());
            }
    
            /// <summary>
            /// 生成Sec-WebSocket-Accept
            /// </summary>
            /// <param name="handShakeText">客户端握手信息</param>
            /// <returns>Sec-WebSocket-Accept</returns>
            private static string GetSecKeyAccetp(byte[] handShakeBytes, int bytesLength)
            {
                string handShakeText = Encoding.UTF8.GetString(handShakeBytes, 0, bytesLength);
                string key = string.Empty;
                Regex r = new Regex(@"Sec-WebSocket-Key:(.*?)
    ");
                Match m = r.Match(handShakeText);
                if (m.Groups.Count != 0)
                {
                    key = Regex.Replace(m.Value, @"Sec-WebSocket-Key:(.*?)
    ", "$1").Trim();
                }
                byte[] encryptionString = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
                return Convert.ToBase64String(encryptionString);
            }
    
            /// <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;
            }
        }
    }

    session类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Sockets;
    using System.Text;
    
    namespace WebSocket
    {
        public class Session
        {
            private Socket _sockeclient;
            private byte[] _buffer;
            private string _ip;
            private bool _isweb = false;
    
            public Socket SockeClient
            {
                set { _sockeclient = value; }
                get { return _sockeclient; }
            }
    
            public byte[] buffer
            {
                set { _buffer = value; }
                get { return _buffer; }
            }
    
            public string IP
            {
                set { _ip = value; }
                get { return _ip; }
            }
    
            public bool isWeb
            {
                set { _isweb = value; }
                get { return _isweb; }
            }
        }
    }
    萌橙 你瞅啥?
  • 相关阅读:
    年末反思
    Flink运行时架构
    Phoenix 启动报错:Error: ERROR 726 (43M10): Inconsistent namespace mapping properties. Cannot initiate connection as SYSTEM:CATALOG is found but client does not have phoenix.schema.
    Clickhouse学习
    Flink简单认识
    IDEA无法pull代码到本地,Can't Update No tracked branch configured for branch master or the branch doesn't exist.
    第1章 计算机系统漫游
    简单的 Shell 脚本入门教程
    开源≠免费 常见开源协议介绍
    MySQL 视图
  • 原文地址:https://www.cnblogs.com/daimaxuejia/p/9335756.html
Copyright © 2020-2023  润新知