Socket服务器-Websocket支持多端连入

摘要:
套接字服务器:usingSystem;使用System.Collections。通用的使用系统。Linq;使用系统。网使用System.Net。插座;使用System.Security。密码学;使用系统。文本使用System.Text。正则表达式;我们

socket服务端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
    class Program
    {
        static List<Socket> Sockets = new List<Socket>();
        //static Socket listener = null;
        //static Dictionary<string, Socket> ClientConnectionItems = new Dictionary<string, Socket> { };
        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("等待客户端连接....");
                while (true) //该操作用于多个客户端连接
                {
                    Socket sc = listener.Accept();//接受一个连接
                    Sockets.Add(sc); //将连接的客户端, 添加到内存当中
                    Thread t = new Thread(new ThreadStart(() => ReceiveData(sc))); //开启当前Socket线程, 去执行获取数据的动作,与客户端通信
                    t.IsBackground = true;
                    t.Start();
                }
                //Thread threadwatch = new Thread(WatchConnecting);
                //threadwatch.IsBackground = true;
                ////启动线程         
                //threadwatch.Start();
                //Console.WriteLine("开启监听......");
                //Console.ReadKey();
                //listener.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            Console.ReadLine();
        }
        //public static void WatchConnecting()
        //{
        //    Socket connection = null;
        //    while (true)//持续不断监听客户端发来的请求    
        //    {
        //        try
        //        {
        //            connection = listener.Accept();
        //        }
        //        catch (Exception) {
        //            Console.WriteLine();
        //            break;
        //        }
        //        //客户端网络结点号   
        //        string remoteEndPoint = connection.RemoteEndPoint.ToString();
        //        //添加客户端信息             
        //        ClientConnectionItems.Add(remoteEndPoint, connection);
        //        //显示与客户端连接情况           
        //        Console.WriteLine(" [客户端"" + remoteEndPoint + ""建立连接成功! 客户端数量:" + ClientConnectionItems .Count+ "]");
        //        //获取客户端的IP和端口号             
        //        IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address;
        //        int clientPort = (connection.RemoteEndPoint as IPEndPoint).Port;
        //        //让客户显示"连接成功的"的信息             
        //        string sendmsg = "[" + "本地IP:" + clientIP + " 本地端口:" + clientPort.ToString() + " 连接服务端成功!]";
        //        byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendmsg);
        //        connection.Send(arrSendMsg);
        //        //创建一个通信线程                 
        //        Thread thread = new Thread(recv);
        //        //设置为后台线程,随着主线程退出而退出            
        //        thread.IsBackground = true;
        //        //启动线程               
        //        thread.Start(connection);

        //    }
        //}
      
   
    /// <summary> 
    /// 接收客户端发来的信息,客户端套接字对象
    /// </summary>   
    /// <param name="socketclientpara"></param>
    //static void recv(object socketclientpara)
    //{
    //    Socket socketServer = socketclientpara as Socket;
    //    while (true)
    //    {
    //        //创建一个内存缓冲区,其大小为1024*1024字节  即1M
    //        byte[] arrServerRecMsg = new byte[1024 * 1024];
    //        //将接收到的信息存入到内存缓冲区,并返回其字节数组的长度 
    //        try
    //        {
    //            int length = socketServer.Receive(arrServerRecMsg);

    //            //将机器接受到的字节数组转换为人可以读懂的字符串     
    //            string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);
    //            //将发送的字符串信息附加到文本框txtMsg上              
    //            Console.WriteLine(" [客户端:" + socketServer.RemoteEndPoint + " 时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "] " + strSRecMsg);
    //                //

    //                //Thread.Sleep(1000);
    //                //自定义聊天内容
    //                //Console.WriteLine("输入消息: ");
    //                //string s = Console.ReadLine();
    //                //单个客户端
    //                //socketServer.Send(Encoding.UTF8.GetBytes("[" + socketServer.RemoteEndPoint + "]:" + strSRecMsg + " "));
    //                //发送客户端数据           
    //                if (ClientConnectionItems.Count > 0)
    //            {
    //                foreach (var socketTemp in ClientConnectionItems)
    //                {
    //                    socketTemp.Value.Send(Encoding.UTF8.GetBytes("[" + socketServer.RemoteEndPoint + "]:" + strSRecMsg));
    //                }
    //            }
    //        }
    //        catch (Exception)
    //        {
    //            ClientConnectionItems.Remove(socketServer.RemoteEndPoint.ToString());
    //            //提示套接字监听异常     

    //            Console.WriteLine(" [客户端"" + socketServer.RemoteEndPoint + ""已经中断连接! 客户端数量:" + ClientConnectionItems.Count + "]");
    //            //关闭之前accept出来的和客户端进行通信的套接字          
    //            socketServer.Close();
    //            break;
    //        }
    //    }
    //}


    public static void ReceiveData(Socket sc)
        {
            byte[] buffer = new byte[1024];
            Console.WriteLine("接受到了客户端:" + sc.RemoteEndPoint.ToString() + "连接....");
            //握手
            int length = sc.Receive(buffer);//接受客户端握手信息
            sc.Send(PackHandShakeData(GetSecKeyAccetp(buffer, length))); while (true)
            {
                try
                {
                    //接受客户端数据
                    Console.WriteLine("等待客户端数据....");//运行到这步会停止,然后等客户端消息
                    length = sc.Receive(buffer);//接受客户端信息
                    string clientMsg = AnalyticData(buffer, length);
                    Console.WriteLine("接受到客户端数据:" + clientMsg);
                    //发送数据
                    string sendMsg = "服务端返回信息:" + clientMsg;
                    sc.Send(PackData(sendMsg));
                }
                catch (Exception ex)
                {
                    Sockets.Remove(sc);  //如果接收的过程中,断开, 那么内存中移除当前Socket对象, 并且退出当前线程
                    Console.WriteLine("客户端已经断开连接!");
                    return;
                }
            }


        }
        /// <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);
            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;
        }
    }
}

websocket客户端:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="SmartLockerWS.Test" %>

<%--<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form runat="server">
    <div>
            <asp:Button runat="server" Text="Test1" OnClick="btnTest_Click" /><asp:Button runat="server" Text="Test2" OnClick="btnTest2_Click" /><asp:Label runat="server" />
            <asp:GridView runat="server" />
    </div>
    </form>
</body>
</html>--%>
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <script>
var webSocket;
function connect()
{
    try
    {
        var readyState = new Array("正在连接", "已建立连接", "正在关闭连接", "已关闭连接");
        var host = "ws://localhost:10";
        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>

</head>

<body>
    <%--<h1>WebSocket客户端示例</h1>--%>
    <div id="message"></div>
    <p>请输入一些文字</p>
    <input type="text">
    <button onClick="connect();">建立连接</button>
    <button onClick="send();">发送数据</button>
    <button onClick="disconnect();">断开连接</button>

</body>
</html>

或者socket客户端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication2
{
    class Program
    {
        //创建 1个客户端套接字 和1个负责监听服务端请求的线程 
        static Thread threadclient = null;
        static Socket socketclient = null;

        static void Main(string[] args)
        {
            //定义一个套接字监听 
            socketclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //获取文本框中的IP地址 
            IPAddress address = IPAddress.Parse("127.0.0.1");

            //将获取的IP地址和端口号绑定在网络节点上 
            IPEndPoint point = new IPEndPoint(address, 10);

            try
            {
                //客户端套接字连接到网络节点上,用的是Connect 
                socketclient.Connect(point);
            }
            catch (Exception r)
            {
                return;
            }

            threadclient = new Thread(recv);
            threadclient.IsBackground = true;
            threadclient.Start();
            Thread.Sleep(1000);
            Console.WriteLine(socketclient.LocalEndPoint+": ");
            while (true) {
                string s = Console.ReadLine();
                ClientSendMsg(s);
            }
        }

        // 接收服务端发来信息的方法   
       static void recv()
        {
            int x = 0;
            //持续监听服务端发来的消息
            while (true)
            {
                try
                {
                    //定义一个1M的内存缓冲区,用于临时性存储接收到的消息 
                    byte[] arrRecvmsg = new byte[1024 * 1024];

                    //将客户端套接字接收到的数据存入内存缓冲区,并获取长度 
                    int length = socketclient.Receive(arrRecvmsg);

                    //将套接字获取到的字符数组转换为人可以看懂的字符串 
                    string strRevMsg = Encoding.UTF8.GetString(arrRecvmsg, 0, length);
                    if (x == 1)
                    {
                        Console.WriteLine(strRevMsg);
                        }
                    else
                    {
                        Console.WriteLine(strRevMsg + " ");
                        x = 1;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("远程服务器已经中断连接!" + ex.Message + " ");
                    break;
                }
            }
        }

        //获取当前系统时间 
        DateTime GetCurrentTime()
        {
            DateTime currentTime = new DateTime();
            currentTime = DateTime.Now;
            return currentTime;
        }

        //发送字符信息到服务端的方法 
       static void ClientSendMsg(string sendMsg)
        {
            //将输入的内容字符串转换为机器可以识别的字节数组    
            byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
            //调用客户端套接字发送字节数组    
            socketclient.Send(arrClientSendMsg);
            //将发送的信息追加到聊天内容文本框中    
        } 
    }
}

免责声明:文章转载自《Socket服务器-Websocket支持多端连入》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇教你一招:解决Win10 win7 删除文件或文件夹时提示“找不到该项目”angular1.5 组件学习 -- 4.1、组件的其他属性 require下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

c# Socket心跳试验,自定义发送包 和 使用KeepAlive

事前准备下载Wireshark并安装 打开Wireshark,修改过滤规则:ip.src eq 192.168.3.201 or ip.dst eq 192.168.3.201  如图: 不使用KeepAlive网上有段代码,可以对socket进行心跳检测,下面贴出部分代码: bool blockingState = socket...

JQuery EasyUI datagrid 批量编辑和提交

前台主要代码: <script type="text/javascript"> $(function() { var $dg = $("#dg"); $dg.datagrid({ url : "servlet/list", width : 700,...

C#结合js 上传文件和删除文件(技术点有:asp.net mvc ,nhibernate,ajax等)

之前做项目的时候要用到上传文件的功能,现在我总结一下,上传文件和删除文件的代码,在以后的使用的过程中也更方便查找。 [HttpPost] public ActionResult EditUser() { var userDal = new UserDal(); cons...

.NET Core+QQ第三方授权登录

安装包 dotnet add package AspNet.Security.OAuth.QQ 接上文GitHub第三方授权登录 申请过程不介绍了,申请者资料,个人也是可以申请成功的。 这时候有二个参数就是clientid clientsecret APP ID:xxxx APP Key:xxxxxx 其中平台信息,这个申请审核通过后,不要修改,千万不...

Delphi7中 string, AnsiString, Utf8String,WideString的区别分析(转)

Windows系统上的 Notepad.exe 打开文件后,点击“文件”菜单中的“另存为”命令,会跳出一个对话框,在最底部有一个“编码”的下拉条。里面有四个选项:ANSI,Unicode,Unicode big endian 和 UTF-8。1)ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows...

反弹shell的各种姿势

在渗透过程中,往往因为端口限制而无法直连目标机器,此时需要通过反弹shell来获取一个交互式shell,以便继续深入。 反弹shell是打开内网通道的第一步,也是权限提升过程中至关重要的一步。本文所有姿势整理自网络,并基于同一个假设的前提下完成测试和验证。(假设:攻击者主机为:192.168.99.242,本地监听1234端口,如有特殊情况以下会备注说明。...