当前位置: 首页 > news >正文

基于C#的以太网通讯实现:TcpClient异步通讯详解

基于C#的以太网通讯实现:TcpClient异步通讯详解
在现代工业控制和物联网应用中,以太网通讯是一种常见的数据传输方式。本文将介绍如何使用C#实现基于TCP协议的以太网通讯,并通过异步编程提高通讯效率。我们将使用TcpClient类来实现客户端与服务器的连接、数据发送和接收,并详细讲解关键技术点。

1. 概述

以太网通讯基于TCP/IP协议,是一种可靠的、面向连接的通讯方式。在C#中,System.Net.Sockets.TcpClient类提供了对TCP协议的支持,可以方便地实现客户端与服务器之间的通讯。本文将使用异步编程模型(APM)来处理连接、发送和接收数据,以提高程序的响应性和性能。

2. 关键技术点

2.1 TcpClient类

TcpClient是C#中用于实现TCP客户端通讯的核心类。它封装了底层的Socket操作,提供了简单易用的接口。

2.2 数据缓冲区

在通讯过程中,数据通过字节数组(byte[])进行传输。合理设置缓冲区大小可以提高数据传输效率。

2.3 连接超时处理

在网络通讯中,连接超时是一个常见问题。通过设置超时时间,可以避免程序长时间等待无响应的服务器。

3. 代码实现

以下是基于TcpClient的异步通讯实现代码,关键技术点已标识。

3.1 TcpClientAsyncTool类

    public class TcpClientAsyncTool
    {
        TcpClient tcpClient;
        public bool isConnected = false;
        IPAddress iPAddress;
        int port;
        int connectTimeout;
        byte[] receiveBuffer = new byte[1024];
        public TcpClientAsyncTool(string ip, int port, int connectTimeout = 2000)
        {
            tcpClient = new TcpClient();
            this.iPAddress = IPAddress.Parse(ip);
            this.port = port;
            this.connectTimeout = connectTimeout;

        }
        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool Connect(Action connectDelegate, out string errorMsg)
        {
            bool result = false;
            errorMsg = string.Empty;
            try
            {
                IAsyncResult asyncResult = tcpClient.BeginConnect(iPAddress, port, null, null);
                connectDelegate();
                bool success = asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(connectTimeout));//设置连接超时时间为2秒
                tcpClient.EndConnect(asyncResult);
                result = true;
                isConnected = result;
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
            }
            return result;
        }
        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool DisConnect(out string errorMsg)
        {
            bool result = false;
            errorMsg = string.Empty;
            try
            {
                tcpClient.Close();
                isConnected = result;
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool SendData(byte[] sendBytes, out string errorMsg)
        {
            bool result = false;
            errorMsg = string.Empty;
            try
            {
                NetworkStream networkStream = tcpClient.GetStream();
                IAsyncResult asyncResult = networkStream.BeginWrite(sendBytes, 0, sendBytes.Length, null, null);
                networkStream.EndWrite(asyncResult);
                result = true;
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message + ex.StackTrace;
            }
            return result;
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="result"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public byte[] ReceiveData(out bool result, out string errorMsg)
        {
            result = false;
            errorMsg = string.Empty;
            byte[] readByteArray = null;
            try
            {
                NetworkStream networkStream = tcpClient.GetStream();
                IAsyncResult iAsyncResult = networkStream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, null, null);
                int readBytes = networkStream.EndRead(iAsyncResult);
                readByteArray = new byte[readBytes];
                Array.Copy(receiveBuffer, readByteArray, readBytes);
                result = true;
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message + ex.StackTrace;
            }
            return readByteArray;
        }
    }

3.2 使用示例

以下是使用TcpClientAsyncTool类的示例代码,展示了如何连接服务器、发送和接收数据。

3.2.1 socket连接,端口号10010

    tcpClient1 = new TcpConnect.TcpClientAsyncTool(controlBoxWithID1.IP, 10010); // 初始化TcpClient
    tasks.Add(Task.Run(async () =>
    {
        if (tcpClient1.Connect(action, out errorMsg)) // 连接服务器
        {
            isConnected1 = true;
            await Task.Run(new Action(ReaceiveData)); // 启动数据接收任务
        }
    }));

3.2.2 数据接收

提前声明:TcpConnect.TcpClientAsyncTool tcpClient1; TcpClient客户端1

private void ReaceiveData()
{
    while (true)
    {
        try
        {
            bool result = false;
            string errorMsg = string.Empty;
            byte[] readReadBytes = tcpClient1.ReceiveData(out result, out errorMsg); // 接收数据
            if (readReadBytes != null)
            {
             //处理接收数据信息readReadBytes 
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Failed to connect to power supply: {ex.Message}"); // 捕获异常并输出错误信息
        }
        if (isConnected1 == false)
        {
            break; // 如果连接断开,退出循环
        }
    }
}

3.2.2 数据发送

        public void SendData1(byte[] message)
        {
            string errorMsg = string.Empty;
            if (isConnected1)
            {
                tcpClient1.SendData(message, out errorMsg);
            }
        }

4. 关键技术解析

4.1 异步连接

通过BeginConnect和EndConnect方法实现异步连接,避免了主线程阻塞。使用AsyncWaitHandle.WaitOne设置超时时间,防止连接无响应的服务器。

4.2 异步发送和接收数据

使用BeginWrite/EndWrite和BeginRead/EndRead实现异步数据发送和接收,确保通讯过程不会阻塞主线程。

4.3 数据缓冲区

通过byte[]数组作为数据缓冲区,接收到的数据会被存储在该数组中。合理设置缓冲区大小可以提高数据传输效率。

4.4 连接状态管理
通过isConnected变量管理连接状态,确保在连接断开时及时停止数据接收任务。

5. 总结

本文介绍了如何使用C#实现基于TCP协议的以太网通讯,并通过异步编程模型提高了通讯效率。关键技术点包括TcpClient的使用、异步编程模型、数据缓冲区和连接超时处理。通过本文的代码示例,您可以快速实现一个可靠的以太网通讯客户端。

希望这篇文章对您有所帮助!如果有任何问题,欢迎在评论区留言讨论。

相关文章:

  • 设置echarts legend 图例与文字对齐
  • 股指期货有卖不出去的时候吗?
  • 在线 SQL 转 flask SQLAlchemy 模型
  • ctf web入门知识合集
  • 阿里wan2.1本地部署
  • Webpack总结
  • MySQL配置文件my.cnf详解
  • 抽象工厂模式 (Abstract Factory Pattern)
  • 蓝桥杯专项复习——结构体、输入输出
  • 花生好车:重构汽车新零售生态的破局者
  • HTML5前端第三章节
  • Centos离线安装openssl-devel
  • 【深度学习与大模型基础】第5章-线性相关与生成子空间
  • 音视频缓存数学模型
  • AI-医学影像分割方法与流程
  • Spring Validation参数校验
  • P1118 [USACO06FEB] Backward Digit Sums G/S
  • 前端项目的构建流程无缝集成到 Maven 生态系统(一)
  • C Sharp 集合
  • 包装类简单认识泛型
  • 澎湃读报丨多家央媒刊文关注拧紧纪律的螺丝:强化监督推动过紧日子要求落到实处
  • 经济日报评论员:拧紧“带头过紧日子”的制度螺栓
  • 受贿2.61亿余元,陕西省政协原主席韩勇一审被判死缓
  • 上影节公布今年IMAX片单:暗涌、重生与感官的史诗
  • A股午后回暖,三大股指涨跌互现:港口板块重新走强,两市成交近1.1万亿元
  • 俄乌刚谈完美国便筹划与俄乌领导人通话,目的几何?