using IoTClient.Common.Constants;
using IoTClient.Common.Helpers;
using IoTServer.Common;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace IoTServer.Servers.PLC
{
///
/// 西门子PLC 服务端模拟
///
public class SiemensServer : ServerSocketBase
{
private Socket socketServer;
private string ip;
private int port;
List sockets = new List();
DataPersist dataPersist;
public SiemensServer(int port, string ip = null)
{
this.ip = ip;
this.port = port;
dataPersist = new DataPersist("SiemensServer");
}
///
/// 启动服务
///
public void Start()
{
//1 创建Socket对象
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2 绑定ip和端口
var ipaddress = string.IsNullOrWhiteSpace(ip) ? IPAddress.Any : IPAddress.Parse(ip);
IPEndPoint ipEndPoint = new IPEndPoint(ipaddress, port);
socketServer.Bind(ipEndPoint);
//3、开启侦听(等待客户机发出的连接),并设置最大客户端连接数为10
socketServer.Listen(10);
Task.Run(() => { Accept(socketServer); });
}
///
/// 停止服务
///
public void Stop()
{
if (socketServer?.Connected ?? false)
socketServer.Shutdown(SocketShutdown.Both);
socketServer?.Close();
}
///
/// 客户端连接到服务端
///
///
void Accept(Socket socket)
{
while (true)
{
try
{
Socket newSocket = null;
try
{
//阻塞等待客户端连接
newSocket = socket.Accept();
sockets.Add(newSocket);
Task.Run(() => { Receive(newSocket); });
}
catch (SocketException)
{
foreach (var item in sockets)
{
if (item?.Connected ?? false) item.Shutdown(SocketShutdown.Both);
item?.Close();
}
}
}
catch (SocketException ex)
{
if (ex.SocketErrorCode != SocketError.Interrupted)
throw ex;
}
}
}
///
/// 接收客户端发送的消息
///
///
void Receive(Socket newSocket)
{
while (newSocket.Connected)
{
try
{
byte[] requetData1 = new byte[4];
//读取客户端发送过来的数据
requetData1 = SocketRead(newSocket, requetData1.Length);
byte[] requetData2 = new byte[requetData1[3] - 4];
requetData2 = SocketRead(newSocket, requetData2.Length);
var requetData = requetData1.Concat(requetData2).ToArray();
//如果是连接的时候发送的两次初始化指令 则直接跳过
if (requetData[3] == SiemensConstant.Command1_200Smart.Length || requetData[3] == SiemensConstant.Command2_200Smart.Length)
{
newSocket.Send(requetData);
continue;
}
var address = requetData[28] * 256 * 256 + requetData[29] * 256 + requetData[30];
var typeDB = requetData[27];
var stationNumberKey = $"s200-{typeDB}";
switch (requetData[17])
{
//读
case 4:
{
//读取数据长度
var readLength = requetData[23] * 256 + requetData[24];
var value = dataPersist.Read(stationNumberKey);//TODO 数据存在 25、26
var byteArray = JsonConvert.DeserializeObject(value) ?? new byte[65536];
//把存储的数据转为字节数组
//var bytes = JsonConvert.DeserializeObject(value);
//if (string.IsNullOrWhiteSpace(value))
// bytes = BitConverter.GetBytes(0);
var dataContent = new byte[4 + readLength];//可以从报文中获取Length?
DataConvert.StringToByteArray("FF 09 00 04").CopyTo(dataContent, 0);
dataContent[1] = readLength == 1 ? (byte)0x03 : (byte)0x04;//04 byte(字节) 03bit(位)
dataContent[2] = (byte)(readLength / 256);
dataContent[3] = (byte)(readLength % 256);
Buffer.BlockCopy(byteArray, address / 8, dataContent, 4, readLength);
//dataContent[2] dataContent[3] 后半截数据数组的Length
//dataContent[4]-[7] 返回给客户端的数据
byte[] responseData1 = new byte[21 + dataContent.Length];
DataConvert.StringToByteArray("03 00 00 1A 02 F0 80 32 03 00 00 00 01 00 02 00 00 00 00 04 01").CopyTo(responseData1, 0);
//responseData1[8] = 0x03;//1 客户端发送命令 3 服务器回复命令
responseData1[2] = (byte)(responseData1.Length / 256);
responseData1[3] = (byte)(responseData1.Length % 256);
responseData1[15] = (byte)(requetData.Length / 256);
responseData1[16] = (byte)(requetData.Length % 256);
responseData1[20] = requetData[18];
dataContent.CopyTo(responseData1, 21);
//当读取的是字符串的时候[25]存储的后面的数据长度,参考SiemensClient的Write(string address, string value)方法。
//Buffer.BlockCopy(bytes, 0, responseData1, responseData1.Length - bytes.Length, bytes.Length);
newSocket.Send(responseData1);
}
break;
//写
case 5:
{
var value = new byte[requetData.Length - 35];
Buffer.BlockCopy(requetData, 35, value, 0, value.Length);
var byteArray = JsonConvert.DeserializeObject(dataPersist.Read(stationNumberKey)) ?? new byte[65536];
value.CopyTo(byteArray, address / 8);
//存储字节数据到内存
dataPersist.Write(stationNumberKey, JsonConvert.SerializeObject(byteArray));
byte[] responseData1 = new byte[22];
DataConvert.StringToByteArray("03 00 00 16 02 F0 80 32 03 00 00 00 01 00 02 00 01 00 00 05 01 FF").CopyTo(responseData1, 0);
newSocket.Send(responseData1);
}
break;
}
}
catch (Exception ex)
{
//if (newSocket?.Connected ?? false) newSocket?.Shutdown(SocketShutdown.Both);
//newSocket?.Close();
//throw ex;
}
}
}
}
}