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

        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. 10.29 工作笔记 ndk编译C++,提示找不到头文件(ndk-build error: string: No such file or directory)

    ndk编译C++.提示找不到头文件(ndk-build error: string: No such file or directory) 被这个问题弄得愁眉苦脸啊.心想为啥一个string都找不到呢 ...

  2. CIKM 2013 Paper CQARank: Jointly Model Topics and Expertise in Community Question Answering

    中文简单介绍: 本文对怎样在问答社区对用户主题兴趣及专业度建模分析进行了研究,而且提出了针对此问题的统计图模型Topics Expertise Model. 论文出处:CIKM'13. 英文摘要: C ...

  3. Hadoop的目录结构

  4. Webkit 的麻烦和解决

    * placeholder 在 focus 状态下内容为空时,依然显示文字.和 IE11,Firefox 均不一致: input:focus::-webkit-input-placeholder { ...

  5. Spring4+SpringMVC+MyBatis登录注册详细

    项目结构: package com.mstf.controller; import org.springframework.stereotype.Controller; import org.spri ...

  6. codeforces 501 B Misha and Changing Handles 【map】

    题意:给出n个名字变化,问一个名字最后变成了什么名字 先用map顺着做的,后来不对, 发现别人是将变化后的那个名字当成键值来做的,最后输出的时候先输出second,再输出first 写一下样例就好理解 ...

  7. Java中将String转json对象

    import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple. ...

  8. 首家5G体验厅在深圳建成

    日前,深圳移动卓越时代营业厅推出5G全方位体验活动,让市民亲身感受5G时代到来.据悉,十大5G展示项目生动展现移动5G带来的生活巨变与产业升级,为5G发展汇聚各界力量加速创新落地. 现场有市民表示,5 ...

  9. iptables指南

    在了解iptables之前我们先了解一下 防火墙 的概念防火墙是由Check Point创立者Gil Shwed于1993年发明并引入国际互联网,防火墙也是一种位于内部网络与外部网络之间的网络安全系统 ...

  10. Mac系统下安装pip

    Mac下 pip的安装 编译 Python3.7 终端输入: curl https://bootstrap.pypa.io/get-pip.py | python3 1 安装完成,检查版本信息 pip ...