基本信息
源码名称:C#基于UDP欧姆龙PLC通信程序
源码大小:0.53M
文件格式:.zip
开发语言:C#
更新时间:2019-09-18
   友情提示:(无需注册或充值,赞助后即可获取资源下载链接)

     嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):78630559

本次赞助数额为: 2 元 
   源码介绍


using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace CableRobot.Fins
{
    /// <summary>
    /// Allows to write and read PLC memory 允许读写PLC内存
    /// </summary>
    public class FinsClient : IDisposable
    {   
        /// <summary>
        /// 声明类对象 
        /// </summary>
        private readonly CancellationTokenSource _cancellationTokenSource;
        private readonly CancellationToken _cancellationToken;
        private readonly UdpClient _udpClient;
        private readonly FinsResponse[] _responses = new FinsResponse[256];
        private readonly Thread _readerThread;
        private readonly object _lockObject = new object();
        private byte _sid;
        
        public FinsClient(IPEndPoint remoteIpEndPoint)/////
        {
            ///创建一个UdpClient对象,0表示系统自动分配发送端口
            _udpClient = new UdpClient();
            _udpClient.Connect(remoteIpEndPoint);
            
            _cancellationTokenSource = new CancellationTokenSource();
            _cancellationToken = _cancellationTokenSource.Token;///用于监听是否取消每一个任务或线程
            ///创建 _readerThread线程。此处用线程是为了避免阻塞
            _readerThread = new Thread(ReadWorker);
            ///调用Staet()函数启动 _readerThread线程
            _readerThread.Start();
            ///int Array.Length函数:获取数组所有维度中元素的总数
            for (int i = 0; i < _responses.Length; i  )
                _responses[i] = new FinsResponse((byte)i, null);

            Timeout = TimeSpan.FromSeconds(2);
        }
        
        /// <summary>
        /// Gets or sets response timeout设置相应超时
        /// </summary>
        public TimeSpan Timeout { get; set; }/////
        
        public void Close()/////
        {
            _cancellationTokenSource.Cancel();
            ///阻塞调用线程,直到此实例所表示的线程终止,
            _readerThread.Join();
        }

        /// <summary>
        /// Syncroniously reads specified number of ushorts starting from specified address in data memory
        /// 从数据内存中指定的地址开始同步读取指定数量的ushort
        /// </summary>
        /// <param name="startAddress">Address to start to read from</param>
        /// <param name="count">Number of ushorts to read</param>
        /// <returns>Read data</returns>
        public ushort[] ReadData(ushort startAddress, ushort count)/////
        {
            var sid = IncrementSid();
            var cmd = FinsDriver.ReadDataCommand(new Header(sid, true), startAddress, count);
            return Read(sid, cmd);
        }

        /// <summary>
        /// Syncroniously reads specified number of ushorts starting from specified address in work memory
        /// </summary>
        /// <param name="startAddress">Address to start to read from</param>
        /// <param name="count">Number of ushorts to read</param>
        /// <returns>Read data</returns>
        public ushort[] ReadWork(ushort startAddress, ushort count)/////
        {
            var sid = IncrementSid();
            var cmd = FinsDriver.ReadWorkCommand(new Header(sid, true), startAddress, count);
            return Read(sid, cmd);
        }

        /// <summary>
        /// Syncroniously writes specified data to specified address of data memory
        /// </summary>
        /// <param name="startAddress">Address to start write to</param>
        /// <param name="data">Data to write</param>
        public void WriteData(ushort startAddress, ushort[] data)/////
        {
            var sid = IncrementSid();
            var cmd = FinsDriver.WriteDataCommand(new Header(sid, true), startAddress, data);
            Write(sid, cmd);
        }

        /// <summary>
        /// Syncroniously writes specified data to specified address of work memory
        /// </summary>
        /// <param name="startAddress">Address to start write to</param>
        /// <param name="data">Data to write</param>
        public void WriteWork(ushort startAddress, ushort[] data)/////  
        {
            var sid = IncrementSid();
            var cmd = FinsDriver.WriteWorkCommand(new Header(sid, true), startAddress, data);
            Write(sid, cmd);
        }

        /// <summary>
        /// Asynchronously reads specified number of ushorts starting from specified address in data memory
        /// </summary>
        /// <param name="startAddress">Address to start to read from</param>
        /// <param name="count">Number of ushorts to read</param>
        /// <returns>Read data</returns>
        public async Task<ushort[]> ReadDataAsync(ushort startAddress, ushort count)
        {
            var sid = IncrementSid();
            var cmd = FinsDriver.ReadDataCommand(new Header(sid, true), startAddress, count);
            return (await CommandAsync(sid, cmd)).Data;
        }

        /// <summary>
        /// Asynchronously writes specified data to specified address of data memory
        /// </summary>
        /// <param name="startAddress">Address to start to write to</param>
        /// <param name="data">Data to write</param>
        public async Task WriteDataAsync(ushort startAddress, ushort[] data)
        {
            var sid = IncrementSid();
            var cmd = FinsDriver.WriteDataCommand(new Header(sid, true), startAddress, data);
            await CommandAsync(sid, cmd);
        }

        /// <summary>
        /// Writes specified data to specified address of data memory without
        /// </summary>
        /// <param name="startAddress">Address to start to read from</param>
        /// <param name="count">Number of ushorts to read</param>
        public void WriteDataNoResponse(ushort startAddress, ushort[] data)
        {
            var sid = IncrementSid();
            var cmd = FinsDriver.WriteDataCommand(new Header(sid, false), startAddress, data);
            _udpClient.SendAsync(cmd, cmd.Length);
        }
        
        private byte IncrementSid()
        {
            byte sid;
            lock (_lockObject)
            {
                _sid  ;
                sid = _sid;
            }

            _responses[sid].Reset();
            return sid;
        }
        
        private ushort[] Read(byte sid, byte[] cmd)
        {
            if (_udpClient.Send(cmd, cmd.Length) != cmd.Length)
                throw new Exception();
            if (!_responses[sid].WaitEvent.WaitOne(Timeout))
                throw new TimeoutException();
            return _responses[sid].Data;
        }

        private void Write(byte sid, byte[] cmd)
        {
            if (_udpClient.Send(cmd, cmd.Length) != cmd.Length)
                throw new Exception();
            if (!_responses[sid].WaitEvent.WaitOne(Timeout))
                throw new TimeoutException();
        }

        private async Task<FinsResponse> CommandAsync(byte sid, byte[] cmd)
        {
            if (await _udpClient.SendAsync(cmd, cmd.Length) != cmd.Length)
                throw new Exception();
            if (!_responses[sid].WaitEvent.WaitOne(Timeout))
                throw new TimeoutException();
            return _responses[sid];
        }
        
        private void ReadWorker()
        {
            try
            {
                while (true)
                {
                    var task = _udpClient.ReceiveAsync(); ///返回由远程主机异步发送的UDP数据报
                    task.Wait(_cancellationToken);
                    
                    if (task.IsFaulted)
                        throw new AggregateException(task.Exception);

                    FinsDriver.ProcessResponse(task.Result, _responses);
                }
            }
            catch (OperationCanceledException)
            {
            }
        }
        
        public void Dispose()
        {
            _cancellationTokenSource?.Cancel();
            _readerThread?.Join();
            _udpClient?.Dispose();
        }
    }
}