1、S7协议通讯流程回顾
1)建立Socket连接:进行TCP三次握手
这里是指要建立socket的tcp连接,是tcp连接而不是udp连接,tcp连接是可靠连接,tcp连接就是要有稳定的IP地址,它是通过字节方式进行通讯,在程序中就是要创建socket对象,利用socket的方式来实现字节的发送和接收,包括解析数据,这个socket是连接谁呢?肯定是连接plc设备,所以plc设备必须有IP地址,端口号,那么谁去连接了,当然是我们的PC电脑,电脑在这个场景下就是我们的上位机,软件工程师通过开发应用程序来与PLC通讯,模型如下:

2)COTP的握手请求(请求建立通信)
在“握手”之后,并不能马上进行数据交换,需要进行这一步的操作,即客户端发送COTP报文给服务端,在COTP报文中包含“连接请求”和“Destination TSAP”,以明确CPU的机架号和槽号;服务端应答COTP报文,包含“连接确认”;这样服务端就清楚了客户端需要和哪个CPU来进行数据通讯。在这个过程中,有非常标准和严重要求的报文格式,这个过程会有22个字节,每个报文的字段内容代表不同的含义,千万不能搞错,否则服务器,也就是PLC就会不搭理你。报文信息如下,搞不懂没有关系,后面的文章会详细介绍,手摸手教,服务到位,包你满意。

3)S7COMM的握手请求(请求建立操作通信)
在成功完成上面的COTP请求后,现在客户端发送S7 Communicaton报文给服务端,在S7Communicaton报文中包含“通讯请求”; 服务端反馈S7 Communicaton报文。同样的报文中每个字段都有含义,必须严格遵守,这个过程是交换通信信息,共25个字节,报文信息如下:搞不懂没有关系,后面的文章会详细介绍,手摸手教,服务到位,包你满意。
4) 进行读写操作(S7协议报文)
在成功完成上面的1,2,3的三个过程后,现在才是读、写、PLC启停、时间、上传下载等,读取的报文比写入的报文要简单些,但报文结构确实复杂,需要大师给你开光,现在搞不懂没有关系,后面的文章会详细介绍,手摸手教,服务到位,包你满意。

2、开搞socket连接
1)安装西门子博途v15环境
应用环境要求是win10企业版,搭建这个西门子PLC的环境还是蛮消耗时间,精力和能力,耐心的,要求也高,这个事情必须做好,不能偷懒,绝不能失败,否则整个系列的内容就实现不了,具体安装过程请看下面文章,这里不展示,因为过程实在是众多,需要细致。
windows10企业版安装西门子博途V15---01准备环境_博途v15.1安装需求-CSDN博客
windows10企业版安装西门子博途V15---02安装软件_博图v15软件安装步骤-CSDN博客
windows10企业版安装西门子博途V15---03安装仿真软件_西门子v15仿真软件-CSDN博客
windows10企业版安装西门子博途V15---04连接测试_博图v15第一次连接plc步骤-CSDN博客
1)西门子PLC存储区简介
I:数字量输入(DI)
Q:数字量输出
AI:模拟量输入
AQ:模拟量输出
V:变量存储区
M:位存储区
T:定时器存储区
C:计数器存储区
HC:高速计数器
AC:累加器
SM:特殊存储器
L:局部存储区
S:顺序控制继电器
DB:数据块
2)访问规则:bit、B、W、D B:byte W:word ->2byte D:double->4byte Bit: I0.0
DataType:
0x01 - BIT:一个无符号的bit
 0x02 - BYTE:一个8位的数字
 0x03 - CHAR:一个字符
 0x04 - WORD:两个字节宽的无符号整数
 0x05 - INT:两个字节宽的有符号整数。
 0x06 - DWORD:四字节宽的无符号整数
 0x07 - DINT:四字节宽的有符号整数
 0x08 - REAL:四个字节宽的IEEE浮点数
 0x1c - COUNTER:PLC程序计数器使用的计数器类型
 示例:变量的示例地址是DB123X 2.1,它访问DB块123的第3个Byte的第2个Bit。 
3)在本应用中,创建了一个192.168.1.66的PLC设备和hnplc项目,如图

2)创建vs项目
 

 
3、连接代码   
 
 
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace west.siemenscomm
{
    internal class Program
    {
        /// <summary>
        /// plc的ip地址
        /// </summary>
        static string _ip="192.168.1.66";
        /// <summary>
        /// 端口号
        /// </summary>
        static int _port=102;
        /// <summary>
        /// 机柜号,插槽号
        /// </summary>
        static byte _rack=0, _slot=1;
        /// <summary>
        /// socket对象
        /// </summary>
        static Socket socket = null;
        /// <summary>
        /// 时间事件
        /// </summary>
        static ManualResetEvent TimeoutObject = new ManualResetEvent(false);
        /// <summary>
        /// 连接状态 
        /// </summary>
        static bool connectState = false;
        static void Main(string[] args)
        {
            Connect();
            Console.ReadKey();
        } 
        private static void Connect(int timeout = 50)
        {
            TimeoutObject.Reset();
            try
            {
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.BeginConnect(_ip, _port, callback =>
                {
                    connectState = false;
                    var cbSocket = callback.AsyncState as Socket;
                    if (cbSocket != null)
                    {
                        connectState = cbSocket.Connected;
                        if (cbSocket.Connected)
                            cbSocket.EndConnect(callback);
                    }
                    TimeoutObject.Set();
                }, socket);
                TimeoutObject.WaitOne(2000, false);
            }
            catch (SocketException ex)
            {
                if (ex.ErrorCode == 10060)
                    Console.WriteLine(ex.Message);
            }
            if (socket == null || !socket.Connected || ((socket.Poll(200, SelectMode.SelectRead) && (socket.Available == 0))))
            {
               Console.WriteLine("网络连接失败");
            }
            Console.WriteLine(connectState==true?"连接成功":"连接失败");
        }
    }
}
  
一定注意一个问题,看这里


4)运行测试

3、小结
这就是第一个流程,建立TCP的三次握手,它是通过socket对象通讯实现的,小伙伴们,明白了不?下节继续硬起来。
原创不易,打字截图不易,走过路过,不要错过,欢迎点赞,收藏,转载,复制,抄袭,留言,动动你的金手指,早日实现财务自由













![[C++探索]初始化列表,static成员,友元函数,内部类,匿名对象](https://i-blog.csdnimg.cn/direct/19dcd92f5b9d410e8f85ee474630f980.gif)







