using McProtocol.Mitsubishi; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace 常用工具集.Utility.Network.Mitsubishi { internal class MC3EServer { public delegate void DataChanged(int address); public delegate void LogChanged(string message); public event DataChanged DataChangedEvent; public event LogChanged LogChangedEvent; private TcpListener _listener; private bool _isRunning; public static ushort[] _dataStorage = new ushort[65535]; // 初始化数据存储区; // 65535个地址数据,类型为ushort public MC3EServer(int port) { _listener = new TcpListener(IPAddress.Any, port); } public void Start() { new Thread(() => { _isRunning = true; _listener.Start(); LogChangedEvent?.Invoke("MC-3E Protocol Server started..."); while (_isRunning) { try { TcpClient client = _listener.AcceptTcpClient(); Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient)); clientThread.Start(client); } catch (SocketException) { continue; } catch (ThreadInterruptedException) { break; } } }).Start(); } public void Stop() { _isRunning = false; _listener.Stop(); } private void HandleClient(object obj) { TcpClient client = (TcpClient)obj; try { NetworkStream stream = client.GetStream(); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0) { LogChangedEvent?.Invoke($"Received {bytesRead} bytes from client."); // 解析MC-3E协议请求 byte[] response = ProcessMc3ERequest(buffer, bytesRead, out bool write, out int address); // 发送响应 stream.Write(response, 0, response.Length); if (write) Task.Run(() => DataChangedEvent?.Invoke(address)); } } catch (Exception ex) { LogChangedEvent?.Invoke(ex.Message); } client.Close(); } private byte[] ProcessMc3ERequest(byte[] request, int length, out bool write, out int address) { // MC-3E协议帧格式示例: // 子头 (2字节) + 网络编号 (1字节) + PLC编号 (1字节) + 请求目标模块IO编号 (2字节) + 请求目标模块站号 (1字节) // + 请求数据长度 (2字节) + 请求数据 (N字节) // 解析请求数据 if (length < 8) { LogChangedEvent?.Invoke($"Invalid request length."); write = false; address = 0; return BuildErrorResponse(); } McFrame mcFrame = new McFrame(); mcFrame.Frame = BitConverter.ToUInt16(request, 0); // 假设前两字节为帧类型 0x0050 80 mcFrame.NetworkNumber = request[2]; // 假设第3字节为网络编号 mcFrame.PcNumber = request[3]; // 假设第4字节为PLC编号 mcFrame.IoNumber = BitConverter.ToUInt16(request, 4); // 假设第5-6字节为模块IO编号 mcFrame.ChannelNumber = request[6]; // 假设第7字节为模块站号 int dataLength = BitConverter.ToUInt16(request, 7); // 假设第8-9字节为数据长度 mcFrame.CpuTimer = BitConverter.ToUInt16(request, 9); // 假设第10-11字节为CPU监视定时器 int mainCommand = BitConverter.ToUInt16(request, 11); // 假设第12-13字节为主命令 int subCommand = BitConverter.ToUInt16(request, 13); // 假设第14-15字节为子命令 mcFrame.Address = request[17] << 16 | request[16] << 8 | request[15]; mcFrame.Type = (PlcDeviceType)request[18]; mcFrame.Size = BitConverter.ToUInt16(request, 19); byte[] data = new byte[mcFrame.Size * 2]; for (int i = 0; i < data.Length; i++) { data[i] = request[21 + i]; } mcFrame.Data = data; // 处理读请求 if (mainCommand == 0x0401) //读命令 { LogChangedEvent?.Invoke($"Read request: Address={mcFrame.Address},Type={mcFrame.Type} Count={mcFrame.Size}"); write = false; address = 0; return HandleReadRequest(mcFrame); } // 处理写请求 else if (mainCommand == 0x1401) // 写命令 { LogChangedEvent?.Invoke($"Write request: Address={mcFrame.Address},Type={mcFrame.Type} Count={mcFrame.Size}"); write = true; address = mcFrame.Address; return HandleWriteRequest(mcFrame); ; } else { LogChangedEvent?.Invoke("Unknown command."); write = false; address = 0; return BuildErrorResponse(); } } class McFrame { public ushort Frame { get; set; } // 头部 public byte NetworkNumber { get; set; } // 网络号码 public byte PcNumber { get; set; } // 电脑号码 public ushort IoNumber { get; set; } // 请求单元 I/O 编号/O番号 public byte ChannelNumber { get; set; } // 请求单位站号 public ushort CpuTimer { get; set; } // 中央处理器监控计时器 public int Address { get; set; } // 地址 public PlcDeviceType Type { get; set; } // 类型 public uint Size { get; set; } // 大小 public byte[] Data { get; set; } } private byte[] HandleReadRequest(McFrame mcFrame) { // 读取数据 List responseData = new List(); // 每个ushort占2字节 for (int i = 0; i < mcFrame.Size; i++) { byte[] valueBytes = BitConverter.GetBytes(_dataStorage[mcFrame.Address + i]); responseData.AddRange(valueBytes); } // 构建响应帧 return BuildSuccessResponse(mcFrame, responseData.ToArray()); } private byte[] HandleWriteRequest(McFrame mcFrame) { for (int i = 0; i < mcFrame.Size; i++) { _dataStorage[mcFrame.Address + i] = BitConverter.ToUInt16(mcFrame.Data, i * 2); } LogChangedEvent?.Invoke($"Write successful: Address={mcFrame.Address}, Length={mcFrame.Size}"); return BuildSuccessResponse(mcFrame, new byte[0]); // 写入成功,返回空响应 } private byte[] BuildSuccessResponse(McFrame mcFrame, byte[] responseData) { // 构建成功响应帧 List response = new List(); mcFrame.Frame = 0x00D0; response.AddRange(BitConverter.GetBytes(mcFrame.Frame));//0 1 response.Add(mcFrame.NetworkNumber); //2 response.Add(mcFrame.PcNumber); //3 response.AddRange(BitConverter.GetBytes(mcFrame.IoNumber)); //4 5 response.Add(mcFrame.ChannelNumber);//6 //response.AddRange(BitConverter.GetBytes(mcFrame.CpuTimer)); //数据长度 response.AddRange(BitConverter.GetBytes((short)(responseData.Length + 2)));//7 8 response.AddRange(BitConverter.GetBytes((short)0));//9 10结束符号 response.AddRange(responseData); return response.ToArray(); } private byte[] BuildErrorResponse() { // 构建错误响应帧 byte[] response = new byte[8]; // 子头 (2字节) response[0] = 0xD0; response[1] = 0x00; // 网络编号 (1字节) response[2] = 0x00; // PLC编号 (1字节) response[3] = 0xFF; // 模块IO编号 (2字节) response[4] = 0x00; response[5] = 0x00; // 模块站号 (1字节) response[6] = 0x00; // 响应数据长度 (2字节) response[7] = 0x00; response[8] = 0x00; return response; } } }