c#Socket 异步通讯(客户端与服务端)

2023-11-19

c#Socket 异步通讯(多个客户端与服务端)

最近公司有个项目,涉及到的通讯对象有点多,就拿其中一个库的通讯来说就用到了3个PLC,这里就涉及了一个服务器与多个客户端之间的通讯了,同时上位机既需要做客户端,也需要做服务端,因为跟PLC之间走的Modbus tcp。

下面直接上代码吧:

客户端

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

namespace Communication.CommType
{
    public class AsynClient
    {
        public  class StateObject
        {
            // 当前客户端的Socket
            public   Socket workSocket = null;
            // 可接收的最大字节数
            public  const int BufferSize = 20200;
            // 接收的数据存储
            public   byte[] buffer = new byte[BufferSize];           
        }
        public static  List<byte> RevBuf;
        public static  bool _BoolRevContent = false;
        public static bool BoolRevContent
        {
            get { return _BoolRevContent; }
            set { _BoolRevContent = value; }
        }
        public static Socket clientT;
        public static bool ConnectServercer(string ip, string port)
        {
            try
            {
                IPAddress IP = IPAddress.Parse(ip);
                IPEndPoint Point = new IPEndPoint(IP, int.Parse(port));
                clientT = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientT.BeginConnect(Point, new AsyncCallback(ConnectCallback), clientT);
                //connectDone.WaitOne();
                //byte[] A = new byte[] { 0x00, 0x02, 0x06 };
                //Send(client, A);
                //sendDone.WaitOne();
                Receive(clientT);
                //receiveDone.WaitOne();                
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        private static void ConnectCallback(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState;
            client.EndConnect(ar);
            //connectDone.Set();
        }
        private static  void Receive(Socket client)
        {
            StateObject state = new StateObject();
            state.workSocket = client;
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
        }

        public static void ReceiveCallback(IAsyncResult ar)
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;
            int bytesRead = client.EndReceive(ar);
            //byte[] Conn = state.buffer;
            if (bytesRead > 0)
            {              
                BoolRevContent = true;
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
                RevBuf = new List<byte>();
                byte[] ActConn = new byte[bytesRead];
                Buffer.BlockCopy(state.buffer, 0, ActConn, 0, bytesRead);
                RevBuf.AddRange(ActConn);
                BoolRevContent = false;
            }
            else
            {

            }
        }

        public static  bool Send(byte[] data)
        {          
            try
            {
                clientT.BeginSend(data, 0, data.Length, 0, new AsyncCallback(SendCallback), clientT);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        private static  void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.
                Socket client = (Socket)ar.AsyncState;
                // Complete sending the data to the remote device.
                int bytesSent = client.EndSend(ar);
                // Signal that all bytes have been sent.
                //sendDone.Set();
            }
            catch (Exception e)
            {

            }
        }
    }
}

服务端

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

namespace Communication.CommType
{
    public class AsynServer
    {
        public class StateObject
        {
            // Client socket.
            public Socket workSocket = null;
            // Size of receive buffer.
            public const int BufferSize = 22000;
            // Receive buffer.
            public byte[] buffer = new byte[BufferSize];
            // Received data string.
            public StringBuilder sb = new StringBuilder();
        }

        public static string ErrorMsg = string.Empty;
        /// <summary>
        /// public delegate void MyDelegate(string S);
        public delegate void MyDelegate(string S);
        public static event MyDelegate MyEvent = null;
        /// <summary>
        /// 将事件设置成单例模式
        /// </summary>
        public class Singleton
        {
            private static Singleton _instance = null;

            private Singleton()
            {
                MyEvent = null;
            }
            public static Singleton CreateInstance()
            {
                if (_instance == null)
                {
                    _instance = new Singleton();
                }
                return _instance;
            }
        }
        /// </summary>
        public static  byte[] SendBuf = new byte[] { };
        /// <summary>
        /// 接收的字节
        /// </summary>
        public static  List<byte> RevBuf;
        /// <summary>
        /// 当前发送数据的客户端
        /// </summary>
        public static  IPEndPoint _CurrentClient;
        public static  IPEndPoint CurrentClient
        {
            get { return _CurrentClient; }
            set { _CurrentClient = value; }
        }

        /// <summary>
        /// 触发接收消息的委托
        /// </summary>
        public static bool _RevBool = false;
        public static event EventHandler RevBoolChanged = null;
        public static bool RevBool
        {
            get { return _RevBool; }
            set
            {
                if (_RevBool != value)
                {
                    _RevBool = value;
                    if (_RevBool)
                    {
                        RevBoolChanged?.Invoke(0, EventArgs.Empty);
                    }
                }
            }
        }
        /// <summary>
        /// 存储客户端连接Socket
        /// </summary>
        public static  Dictionary<string, Socket> clientConnectionItems = new Dictionary<string, Socket> { };
        /// <summary>
        /// 打开服务器
        /// </summary>
        /// <returns></returns>
        public static  bool OpenServer(string Ip, string Port)
        {
            try
            {
                IPAddress IP = IPAddress.Parse(Ip);
                IPEndPoint Point = new IPEndPoint(IP, int.Parse(Port));
                Socket ServerClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                ServerClient.Bind(Point);
                ServerClient.Listen(10);
                ServerClient.BeginAccept(new AsyncCallback(AcceptCallback), ServerClient);
                MyEvent("服务器打开成功");
                //thServer = new Thread(new ThreadStart(RevState));
                //thServer.IsBackground = true;
                //thServer.Start();
                return true;
            }
            catch (Exception ex)
            {
                ErrorMsg = ex.Message;
                MyEvent("服务器打开失败:"+ex.Message);
                return false;
            }
        }
        /// <summary>
        /// 连接回调
        /// </summary>
        /// <param name="ar"></param>
        public static  void AcceptCallback(IAsyncResult ar)
        {
            try
            {
                Socket listener = ar.AsyncState as Socket;
                if (listener != null)
                {
                    Socket handler = listener.EndAccept(ar);
                    StateObject state = new StateObject();
                    state.workSocket = handler;
                    IPEndPoint clientipe = (IPEndPoint)handler.RemoteEndPoint;
                    //txt_State.AppendText(clientipe.ToString() + "连上咯" + "\r\n");
                    clientConnectionItems.Add(clientipe.ToString(), handler);
                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(RevCallback), state);
                    MyEvent(clientipe.ToString()+"----已连上服务器");
                }
                if (listener != null)
                {
                    listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                }
            }
            catch (Exception ex)
            {
                ErrorMsg = ex.Message;
                MyEvent(ErrorMsg);
            }
        }
        /// <summary>
        /// 接收回调
        /// </summary>
        /// <param name="ar"></param>
        public static  void RevCallback(IAsyncResult ar)
        {
            StateObject state = (StateObject)ar.AsyncState;
            //Socket socketClient= ar.AsyncState as Socket;
            Socket handler = state.workSocket;
            if (handler != null)
            {
                IPEndPoint clientipe = (IPEndPoint)handler.RemoteEndPoint;
                try
                {
                    // Read data from the client socket.
                    int bytesRead = handler.EndReceive(ar);
                    if (bytesRead > 0)
                    {
                        byte[] a = new byte[bytesRead]; 
                        RevBuf = new List<byte>();
                        Buffer.BlockCopy(state.buffer, 0, a, 0, bytesRead);
                        RevBuf.AddRange(a);
                        //txt_Rev.AppendText(RevBuf[0].ToString() + "\r\n");
                        CurrentClient = clientipe;
                        //Send(handler, new byte[] { 0x00, 0x01, 0x02 });
                        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(RevCallback), state);
                        RevBool = true;
                        RevBool = false;
                    }
                }
                catch (Exception ex)
                {
                    ErrorMsg = clientipe.ToString() + "退出";
                    MyEvent(clientipe.ToString() + "----退出"+ex.Message);
                    //txt_State.AppendText(clientipe.ToString() + "退出" + ex.Message);                   
                }
            }

        }
        /// <summary>
        /// 发送回复客户端
        /// </summary>
        /// <param name="handle">客户端的Socket</param>
        public static  void Send(Socket handle)
        {
            // Convert the string data to byte data using ASCII encoding.           
            // Begin sending the data to the remote device.
            if (SendBuf.Length != 0)//确保发送的字节长度不为0
            {
                handle.BeginSend(SendBuf, 0, SendBuf.Length, 0, new AsyncCallback(SendCallback), handle);
            }
            else
            {

            }
        }
        /// <summary>
        /// 发送回调
        /// </summary>
        /// <param name="ar"></param>
        private static void SendCallback(IAsyncResult ar)
        {
            Socket handler = (Socket)ar.AsyncState;
            int bytesSent = handler.EndSend(ar);
            //handler.Shutdown(SocketShutdown.Both);
            //handler.Close();
        }
    }
}

这两个端都是经过实际测试的,PLC都是用的1200的。
在这里插入图片描述
我做的策略是打开服务端的同时连接3个PLC,代码中有几个地方加入了委托,这个的话是根据我实际需求加的,有用到这个代码的朋友不需要委托可以直接去掉就好了。不影响的话在调用此方法的时候记得把委托加入到队列中,否则会报错。

说明:文中有个地方我是把委托 设置成单例模式的,不设置的话会报“未将事例引用到对象的实例”。具体缘由没弄明白。加上单例模式后 就没有报错了。有知道的大佬给小弟解惑解惑。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c#Socket 异步通讯(客户端与服务端) 的相关文章

随机推荐

  • flask-会话机制

    使用flask bootstrap 步骤 1 pip install flask bootstrap 2 进行配置 from flask bootstrap import Bootstrap bootstrap Bootstrap 在 in
  • kafka 监控工具--CMAK

    CMAK previously known as Kafka Manager is a tool for managing Apache Kafka clusters See below for details about the name
  • 二分法总结(超级详细)附带图解

    文章目录 1 二分法 2 时间复杂度 3 二分法的套路 3 1 整数的二分 3 2 实数的划分 四 相关习题 4 1 数的范围 4 2 数的三次方根 1 二分法 二分查找是一个时间效率极高的算法 尤其是面对大量的数据时 其查找效率是极高 时
  • python读取npy文件时,太大不能完全显示,其解决方法

    python读取npy文件时 太大不能完全显示 其解决方法 当用python读取npy文件时 会遇到npy文件太大 用print函数打印时不能完全显示 如以下情况 其解决办法是 添加一行代码 np set printoptions thre
  • 2023汽车行业数字化转型报告

    目前 汽车行业正经历百年未有之大变局 在新一轮科技革命以及减碳 能源形势变革智能化变革推动下 汽车产业正由功能时代向智能时代演进 由 以车为中心 向 以用户为中心 转变 汽车的产品属性 产业价值链和生态结构都面临被颠覆 新的汽车市场格局正在
  • Python爬虫从入门到精通:(33)scrapy中间件_Python涛哥

    中间件 作用 批量拦截请求和响应 爬虫中间件 下载中间件 推荐 拦截请求 篡改请求url 伪装请求头信息 UA Cookie 设置代理 重点 拦截响应 篡改响应数据 详解 我们创建个工程middlePro 爬取百度和搜狗 import sc
  • goto编程练习

    for 的初始化要放到JUMP上边 不然i会一直为1 for 的i 也不能放到括号里边 不然i永远为0 1 include
  • 200smart第二课基本编程

    一 程序块 主程序main和子程序 主程序是执行程序的入口 没有主程序就不知道程序从哪里开始 子程序是一个大型程序中的某个代码 一般是完成某个算法 二 符号表 给变量定义 当我们在编程的时候 需要定义一些符号名称 如下图 程序运行 注释使程
  • MFC重载鼠标停留WM_MOUSEHOVER和离开WM_MOUSELEAVE消息

    1 重载OnMouseMove 消息 在消息的实现中添加代码 void CMainWindow OnMouseMove UINT nFlags CPoint point TRACKMOUSEEVENT tme tme cbSize size
  • 爬虫与反爬虫技术简介

    互联网的大数据时代的来临 网络爬虫也成了互联网中一个重要行业 它是一种自动获取网页数据信息的爬虫程序 是网站搜索引擎的重要组成部分 通过爬虫 可以获取自己想要的相关数据信息 让爬虫协助自己的工作 进而降低成本 提高业务成功率和提高业务效率
  • @JSONField 解决json字符串转对象,对象属性名与json中key不一致,如何接收数据问题

    背景 我有个对象 过来个json 想用这个对象接收json中的值 对象中属性名与json中key值不一致 实现 这个时候 JSONField注解就派上用场了 不能直接放在属性上 要放在set方法上 模拟 1 搞个对象 属性名分别为name
  • 【靶场】upload-labs Pass-02

    考纲 本pass在服务端对数据包的MIME进行检查 在右上角点击 查看提示 中看到 一 上一关 靶场 upload labs Pass 01 二 大马 介绍两款 php 大马 因为 一句话木马看不上 如果师傅有其他好用的 大马 还望师傅在评
  • QT添加qss文件和资源文件

    先右键项目 选择 Add New 选择一个模板 选择 Qt 模板 再选择 Qt Resource Files 点击 Choose 填上资源文件的名称 默认添加项目路径下 后面的步骤默认即可 点击完成 新建完成了资源文件后 默认会进入 res
  • 运放稳定性连载21:电容性负载的稳定性——具有双通道反馈的RISO(2)

    现在 我们必须测量如图10 6所示的Zo 小信号AC开环输出阻抗 该Tina SPICE测试电路将测试空载OPA177的Zo R2和R1以及LT为低通滤波器函数提供了一条AC通道 这样 使得我们能将DC短路和AC开路一起并入反馈电路 DC工
  • ssh报错no key alg(关于低版本连接高版本ssh)

    高版本 8 4 低版本 4 3 按照网上的方法试过 通过ssh keygen命令重新生成ssh主机秘钥 可以不用重启sshd服务 ssh keygen t rsa f etc ssh ssh host rsa key ssh keygen
  • NoReverseMatch: Reverse for ‘data‘ not found . ‘data‘ is not a valid view function or pattern

    Django gt python manage py runserver时报错 NoReverseMatch Reverse for data not found data is not a valid view func tion or
  • 制作一辆“自动驾驶”平衡自行车需要用到哪些知识

    目录 先看下小车效果 小车电路设计 相关软件工具 keil C语言设计编码调试工具 主要 mcuisp 代码烧录工具 一般使用一种烧录工具就可以 STM32 STlink stlink烧录工具 STM32 Cube pro 烧录工具 ope
  • C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现

    本文是转载的 正版是https blog twofei com 496 欢迎去看正版 C 中的虚函数 表 实现机制以及用C语言对其进行的模拟实现 前言 大家都应该知道C 的精髓是虚函数吧 虚函数带来的好处就是 可以定义一个基类的指针 其指向
  • OceanBase使用范例

    http www mysqlops com 2011 08 31 oceanbase use html OceanBase的使用类似于关系型数据库 需要预先创建schema 关于schema的格式 请参见schema说明 假如我们有以下sc
  • c#Socket 异步通讯(客户端与服务端)

    c Socket 异步通讯 多个客户端与服务端 最近公司有个项目 涉及到的通讯对象有点多 就拿其中一个库的通讯来说就用到了3个PLC 这里就涉及了一个服务器与多个客户端之间的通讯了 同时上位机既需要做客户端 也需要做服务端 因为跟PLC之间