服务端代码(控制台示例):

        static List<Socket> Sockets = new List<Socket>();

        static void Main(string[] args)
        {
            ;
            ];

            IPEndPoint localEP = new IPEndPoint(IPAddress.Any, port);
            Socket listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                listener.Bind(localEP);
                listener.Listen();
                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();
                }

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            Console.ReadLine();
        }

        public static void ReceiveData(Socket sc)
        {
            ];
            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;
                }
            }
        }

Socket 相关类

  #region Socket Helper

        /// <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)
        {
            , bytesLength);
            string key = string.Empty;
            Regex r = new Regex(@"Sec\-WebSocket\-Key:(.*?)\r\n");
            Match m = r.Match(handShakeText);
            )
            {
                key = Regex.Replace(m.Value, @"Sec\-WebSocket\-Key:(.*?)\r\n", "$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)
        {
            ) { return string.Empty; }

            ] & 0x80) == 0x80; // 1bit,1表示最后一帧
            if (!fin)
            {
                return string.Empty;// 超过一帧暂不处理
            }

            ] & 0x80) == 0x80; // 是否包含掩码
            if (!mask_flag)
            {
                return string.Empty;// 不包含掩码的暂不处理
            }

            ] & 0x7F; // 数据长度  

            ];
            byte[] payload_data;

            )
            {
                Array.Copy(recBytes, , masks, , );
                payload_len = (UInt16)(recBytes[] <<  | recBytes[]);
                payload_data = new byte[payload_len];
                Array.Copy(recBytes, , payload_data, , payload_len);

            }
            )
            {
                Array.Copy(recBytes, , masks, , );
                ];
                ; i < ; i++)
                {
                    uInt64Bytes[i] = recBytes[ - i];
                }
                UInt64 len = BitConverter.ToUInt64(uInt64Bytes, );

                payload_data = new byte[len];
                ; i < len; i++)
                {
                    payload_data[i] = recBytes[i + ];
                }
            }
            else
            {
                Array.Copy(recBytes, , masks, , );
                payload_data = new byte[payload_len];
                Array.Copy(recBytes, , payload_data, , payload_len);

            }

            ; i < payload_len; i++)
            {
                payload_data[i] = (]);
            }

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

            )
            {
                contentBytes = ];
                contentBytes[] = 0x81;
                contentBytes[] = (byte)temp.Length;
                Array.Copy(temp, , contentBytes, , temp.Length);
            }
            else if (temp.Length < 0xFFFF)
            {
                contentBytes = ];
                contentBytes[] = 0x81;
                contentBytes[] = ;
                contentBytes[] = (byte)(temp.Length & 0xFF);
                contentBytes[] = ( & 0xFF);
                Array.Copy(temp, , contentBytes, , temp.Length);
            }
            else
            {
                // 暂不处理超长内容
            }

            return contentBytes;
        }

        #endregion

客户端连接(网页测试):

<!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: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>
<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>

应用效果:

C# Socket服务端及多客户端连接通信实现的更多相关文章

  1. MongoDB的基本操作:服务端启动,客户端连接,CRUD操作

    本文内容: MongoDB的介绍 MongoDB服务端的启动 MongoDB客户端连接 SQL与MongoDB相关概念解释 什么是BSON 数据库操作 集合操作 文档操作 测试环境:win10 软件版 ...

  2. PHP socket服务端与客户端的简易通信

    今天学习socket通信的同时,顺便整理了下以前初识socket的知识. 现在关于php的socket通信,有些框架已经十分成熟了,比如  swoole 和 workerman,这两个大家可以学习学习 ...

  3. Python3学习之路~8.3 socket 服务端与客户端

    通过8.2的实例1-6,我们可以总结出来,socket的服务端和客户端的一般建立步骤: 服务端 步骤:1创建实例,2绑定,3监听,4阻塞,5发送&接收数据,6关闭. #Author:Zheng ...

  4. AutoCAD.net支持后台线程-Socket服务端

    最近因为公司项目的需求,CAD作为服务端在服务器中常驻运行,等待客户端远程发送执行任务的指令,最终确认用Socket-tcp通讯,CAD需要实时监听客户端发送的消息,这时就需要开启线程执行Socket ...

  5. C# Socket服务端与客户端通信(包含大文件的断点传输)

    步骤: 一.服务端的建立 1.服务端的项目建立以及页面布局 2.各功能按键的事件代码 1)传输类型说明以及全局变量 2)Socket通信服务端具体步骤:   (1)建立一个Socket   (2)接收 ...

  6. 利用多线程使socket服务端可以与多个客户端同时通讯

    利用多线程使socket服务端可以与多个客户端同时通讯 server import socket 1. 符合TCP协议的手机 server = socket.socket(socket.AF_INET ...

  7. Socket探索1-两种Socket服务端实现

    介绍 一次简单的Socket探索之旅,分别对Socket服务端的两种方式进行了测试和解析. CommonSocket 代码实现 实现一个简单的Socket服务,基本功能就是接收消息然后加上结束消息时间 ...

  8. 使用NewLife网络库构建可靠的自动售货机Socket服务端(一)

    最近有个基于tcp socket 协议和设备交互需求,想到了新生命团队的各种组件,所以决定用NewLife网络库作为服务端来完成一系列的信息交互. 第一,首先说一下我们需要实现的功能需求吧 1,首先客 ...

  9. 在python中编写socket服务端模块(二):使用poll或epoll

    在linux上编写socket服务端程序一般可以用select.poll.epoll三种方式,本文主要介绍使用poll和epoll编写socket服务端模块. 使用poll方式的服务器端程序代码: i ...

随机推荐

  1. poj 2513 欧拉回路+并查集推断是否联通+Trie树

    http://poj.org/problem? id=2513 最初看到 第一感觉---map  一看250000的数据量 果断放弃 然后记得曾经看过.trie取代map.尤其当数据量特别大的时候 学 ...

  2. 数位DP CF388D - Fox and Perfect Sets

    题目地址 一个整数perfect集合满足性质:集合中随意两个整数的异或和仍在这个集合中. 求最大数不超过K的perfect集合的个数. 每一个集合都是一个线性的向量空间. .能够通过全然的高斯消元得出 ...

  3. 英语音乐---二、Burning

    英语音乐---二.Burning 一.总结 一句话总结:Burning - Maria Arredondo 玛丽亚·亚瑞唐多(Maria Arredondo),1985年7月6日出生于文内斯拉小镇,挪 ...

  4. Square roots

    Loops are often used in programs that compute numerical results by starting with an approximate answ ...

  5. Adobe CC update (Windows/Mac OS) 独立升级包下载

    Windows 版 xiaogezi.cn Photoshop CC 下载 Download 大小 Size 日期 Date 文档 Notes Adobe Photoshop 14.2.1 Updat ...

  6. datable

    $("#table_d").append("<table id='dmglTable' class='table table-striped table-hover ...

  7. js中return 、return false 、return true、break、continue区别

    在开发中不熟悉这三者区别的同学,一般都知道return可以中止,但会根据字面意思觉得return true 中止当前函数执行,但其后的函数还会继续执行.return false 中止当前函数执行,其后 ...

  8. vue之filter用法

    1.全局写法: 全局过滤器必须写在vue实例创建之前. Vue.filter('testfilter', function (value,text) { // 返回处理后的值 return value ...

  9. caioj 1111 树形动态规划(TreeDP)6: 皇宫看守 (状态设计)

    这道题的难点在于状态怎么设计 这道题要求全部都是安全的,所以我们做的时候自底向上每一个结点都要是安全的 结合前一题当前结点选和不选,我们可以分出四种情况出来 选 安全 选 不安全 不选 安全 不选 不 ...

  10. 紫书 例题 10-12 UVa 1637(概率计算)

    以9元组来代表当前状态,每一元是每一堆剩下的牌数 枚举当前状态所有可以拿掉牌的情况,然后递归下去求 概率,当牌拿完的时候概率为1 那么这里的实现非常的秀,用到了vector来代表9元组 然后还用到了m ...