上一篇,我们读写TCP-S7基本辅助类已完成,
C#使用TCP-S7协议读写西门子PLC(一)-CSDN博客
这里,我们开始进行读写西门子PLC,
西门子PLC作为Socket通信的服务端【TCP-Server】
在读写PLC之前,我们先进行Socket-Client程序编写,用于连接TCP服务端【也就是西门子PLC】,为了方便进行,我们使用部分类partial的方式【当然使用父子继承类亦可】,
新建类文件SiemensS7ProtocolUtil.cs
SiemensS7ProtocolUtil类是部分类,需使用关键字partial
关键的几个函数
(1)连接指定的服务端
public OperateResult<Socket> ConnectPlc(IPEndPoint endPoint, int timeout = 3000)
(2)发送字节数组读写命令并等待服务端反馈结果报文【定长报文】
返回的数据报文的前四个字节代表消息头Header 【指令头报文 03 00 00 1E 前两个0x0300是固定,第三第四 0x001E就是30个字节】
public OperateResult<byte[]> SendDataAndWaitResult(Socket socket, byte[] sendBuffer)
(3)接收一条完整的数据,使用异步接收完成,包含了指令头信息
第一次只接收4个字节,用于校验指令头并获取后续接收的字节数【总字节个数-4】
第二次接收剩余字节,就是【总字节个数-4】
将两次接收的数据拼接到一起,接收反馈数据才完成
private OperateResult<byte[]> ReceiveMessage(Socket socket, int timeout)
源程序如下:
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 PlcSiemesS7Demo
{
/// <summary>
/// 西门子PLC的S7通信,基本Socket-Client封装
/// 主要方法:
/// (1).ConnectPlc(IPEndPoint endPoint, int timeout = 3000)
/// (2).OperateResult<byte[]> SendDataAndWaitResult(Socket socket, byte[] sendBuffer)
/// </summary>
public partial class SiemensS7ProtocolUtil
{
/// <summary>
/// 西门子PLC型号,默认S1500
/// </summary>
SiemensPlcCategory SiemensPlcCategory { get; set; } = SiemensPlcCategory.S1500;
private bool isConnected = false;
/// <summary>
/// 连接PLC的IP地址
/// </summary>
public string IpAddress { get; set; }
/// <summary>
/// 连接PLC的端口,默认102
/// </summary>
public int Port { get; set; } = 102;
/// <summary>
/// 连接或接收数据超时时间
/// </summary>
public int Timeout { get; set; } = 3000;
/// <summary>
/// 通讯类的核心套接字
/// </summary>
public Socket CoreSocket = null;
/// <summary>
/// 是否连接PLC并且握手两次成功
/// </summary>
public bool IsConnected
{
get
{
return CoreSocket != null && isConnected;
}
}
/// <summary>
/// 记录日志事件
/// </summary>
public event Action<string> RecordLogEvent;
/// <summary>
/// 连接指定的服务端,如果连接成功,返回Socket对象
/// </summary>
/// <param name="endPoint"></param>
/// <param name="timeout"></param>
/// <returns></returns>
public OperateResult<Socket> ConnectPlc(IPEndPoint endPoint, int timeout = 3000)
{
this.IpAddress = endPoint.Address.ToString();
this.Port = endPoint.Port;
this.Timeout = timeout;
OperateResult<Socket> operateResult = new OperateResult<Socket>();
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.ReceiveTimeout = timeout;
ManualResetEvent connectDone = new ManualResetEvent(false);
StateObject state = new StateObject();
try
{
state.WaitDone = connectDone;
state.WorkSocket = socket;
socket.BeginConnect(endPoi