345 lines
12 KiB
C#
345 lines
12 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Net.Sockets;
|
||
using System.Net;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using static AutomaticApp.Common.Sockets;
|
||
using AutomaticApp.ViewModels;
|
||
|
||
namespace AutomaticApp.Common
|
||
{
|
||
public class Clinet : SocketObject
|
||
{
|
||
public PushSockets pushSockets;
|
||
|
||
bool IsClose = false;
|
||
/// <summary>
|
||
/// 当前管理对象
|
||
/// </summary>
|
||
Sockets sk;
|
||
/// <summary>
|
||
/// 客户端
|
||
/// </summary>
|
||
TcpClient client;
|
||
/// <summary>
|
||
/// 当前连接服务端地址
|
||
/// </summary>
|
||
IPAddress Ipaddress;
|
||
/// <summary>
|
||
/// 当前连接服务端端口号
|
||
/// </summary>
|
||
int Port;
|
||
/// <summary>
|
||
/// 服务端IP+端口
|
||
/// </summary>
|
||
IPEndPoint ip;
|
||
/// <summary>
|
||
/// 发送与接收使用的流
|
||
/// </summary>
|
||
NetworkStream nStream;
|
||
|
||
/// <summary>
|
||
/// 初始化Socket
|
||
/// </summary>
|
||
/// <param name="ipaddress"></param>
|
||
/// <param name="port"></param>
|
||
public override void InitSocket(IPAddress ipaddress, int port)
|
||
{
|
||
Ipaddress = ipaddress;
|
||
Port = port;
|
||
ip = new IPEndPoint(Ipaddress, Port);
|
||
client = new TcpClient();
|
||
}
|
||
/// <summary>
|
||
/// 初始化Socket
|
||
/// </summary>
|
||
/// <param name="ipaddress">ipd地址</param>
|
||
/// <param name="port">端口</param>
|
||
public override void InitSocket(string ipaddress, int port)
|
||
{
|
||
Ipaddress = IPAddress.Parse(ipaddress);
|
||
Port = port;
|
||
ip = new IPEndPoint(Ipaddress, Port);
|
||
client = new TcpClient();
|
||
}
|
||
/// <summary>
|
||
/// 重写Start方法,其实就是连接服务端
|
||
/// </summary>
|
||
public override void Start()
|
||
{
|
||
Connect();
|
||
}
|
||
/// <summary>
|
||
/// 连接
|
||
/// </summary>
|
||
public bool Connect()
|
||
{
|
||
if (client != null && IsOnline() && client.Connected)
|
||
return true;
|
||
|
||
try
|
||
{
|
||
client.Connect(ip);
|
||
tools.Logging("连接客户端成功,IP:" + Ipaddress + "端口号:" + Port);
|
||
//将是否接收到心跳包判断位 置于false
|
||
IsReturnMsg = System.DateTime.Now;
|
||
//检测当前连接状态
|
||
CheckConnect();
|
||
nStream = new NetworkStream(client.Client, true);
|
||
sk = new Sockets(ip, client, nStream);
|
||
sk.nStream.BeginRead(sk.RecBuffer, 0, sk.RecBuffer.Length, new AsyncCallback(EndReader), sk);
|
||
}
|
||
catch (Exception)
|
||
{
|
||
tools.Logging("连接客户端失败,IP:" + Ipaddress + "端口号:" + Port);
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public DateTime IsReturnMsg = System.DateTime.Now;
|
||
|
||
/// <summary>
|
||
/// 检查链接状态
|
||
/// </summary>
|
||
//private async void CheckConnect()
|
||
//{
|
||
// await Task.Run(() =>
|
||
// {
|
||
// //连接成功等待5秒后 发送心跳包
|
||
// Thread.Sleep(10000);
|
||
// tools.Logging("开始发送心跳包");
|
||
// while ((System.DateTime.Now - IsReturnMsg).TotalSeconds < 150)
|
||
// {
|
||
// //如果没有收到心跳包 就发送一次Get
|
||
// if (!IsCheckConnect)
|
||
// {
|
||
// //发送一次GET
|
||
// SendData(new byte[] { (byte)'G', (byte)'E', (byte)'T' });
|
||
// tools.Logging("发送一次心跳包GET,上一次收到心跳包的时间差为" + (System.DateTime.Now - IsReturnMsg).TotalSeconds + "秒");
|
||
// //等待30秒钟
|
||
// Thread.Sleep(30000);
|
||
// }
|
||
// else //如果处于异常断开情况 则不在发送心跳包
|
||
// {
|
||
// tools.Logging("目前系统由于卫通/下位机原因链接断开,停止发送心跳包GET");
|
||
// break;
|
||
// }
|
||
// }
|
||
// tools.Logging("停止发送心跳包GET");
|
||
// //如果此时还是没有 且不是检查连接状态
|
||
// if (!IsCheckConnect)
|
||
// {
|
||
// //先断开链接
|
||
// Stop();
|
||
// tools.Logging("心跳包超时,主动断开链接,停止发送心跳包GET");
|
||
// //等待30秒钟
|
||
// Thread.Sleep(10000);
|
||
// //初始化
|
||
// InitSocket(Ipaddress.ToString(), Port);
|
||
// //重新链接
|
||
// while (!Connect())
|
||
// {
|
||
// tools.Logging("心跳包超时,重新链接失败!");
|
||
// Thread.Sleep(30000);
|
||
// }
|
||
// tools.Logging("心跳包超时,重新链接成功!");
|
||
// }
|
||
// });
|
||
//}
|
||
bool IsCheckConnect = false;
|
||
private async void CheckConnect()
|
||
{
|
||
if (IsCheckConnect)
|
||
return;
|
||
await Task.Run(() =>
|
||
{
|
||
IsCheckConnect = true;
|
||
//连接成功等待10秒后 发送心跳包
|
||
Thread.Sleep(10000);
|
||
tools.Logging("开始发送心跳包");
|
||
while ((System.DateTime.Now - IsReturnMsg).TotalSeconds < 150)
|
||
{
|
||
//发送一次Get
|
||
SendData(new byte[] { (byte)'G', (byte)'E', (byte)'T' });
|
||
tools.Logging("发送一次心跳包GET,上一次收到心跳包的时间差为" + (System.DateTime.Now - IsReturnMsg).TotalSeconds + "秒");
|
||
//等待30秒钟
|
||
Thread.Sleep(30000);
|
||
}
|
||
tools.Logging("心跳包超时,主动断开链接,停止发送心跳包GET");
|
||
//先断开链接
|
||
Stop();
|
||
//等待10秒钟
|
||
Thread.Sleep(10000);
|
||
//初始化
|
||
InitSocket(Ipaddress.ToString(), Port);
|
||
tools.Logging("心跳包超时,开始初始化并重新链接!");
|
||
IsCheckConnect = false; //允许重新链接并启用异步心跳包
|
||
Connect();
|
||
Thread.Sleep(10000);
|
||
//重新链接
|
||
while (!IsOnline())
|
||
{
|
||
tools.Logging("心跳包超时,重新链接失败!");
|
||
Connect();
|
||
Thread.Sleep(30000);
|
||
}
|
||
tools.Logging("心跳包超时,重新链接成功!");
|
||
});
|
||
}
|
||
/// <summary>
|
||
/// 读取
|
||
/// </summary>
|
||
private void EndReader(IAsyncResult ir)
|
||
{
|
||
Sockets s = ir.AsyncState as Sockets;
|
||
try
|
||
{
|
||
if (s != null)
|
||
{
|
||
if (IsClose && client == null)
|
||
{
|
||
sk.nStream.Close();
|
||
sk.nStream.Dispose();
|
||
return;
|
||
}
|
||
s.Offset = s.nStream.EndRead(ir);
|
||
if (pushSockets != null)
|
||
pushSockets.Invoke(s);//推送至UI
|
||
|
||
if (IsOnline())
|
||
{
|
||
//Thread.Sleep(100);
|
||
sk.nStream.BeginRead(sk.RecBuffer, 0, sk.RecBuffer.Length, new AsyncCallback(EndReader), sk);
|
||
}
|
||
else
|
||
{
|
||
if (Ipaddress.ToString().Equals(tools.GetAppSetting("PLC_IP1")))
|
||
{
|
||
MainWindow.mainViewModel.DoSocket1Connect("断开");
|
||
tools.Logging("站点1目前系统由于卫通/下位机原因链接断开,IP:" + Ipaddress + "端口号:" + Port);
|
||
DoConnect(1);
|
||
}
|
||
else if (Ipaddress.ToString().Equals(tools.GetAppSetting("PLC_IP2")))
|
||
{
|
||
MainWindow.mainViewModel.DoSocket2Connect("断开");
|
||
tools.Logging("站点2目前系统由于卫通/下位机原因链接断开,IP:" + Ipaddress + "端口号:" + Port);
|
||
DoConnect(2);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception skex)
|
||
{
|
||
Sockets sks = s;
|
||
sks.ex = skex;
|
||
sks.ClientDispose = true;
|
||
if (pushSockets != null)
|
||
pushSockets.Invoke(sks);//推送至UI
|
||
}
|
||
}
|
||
|
||
private bool IsDoConnect = false;
|
||
/// <summary>
|
||
/// 检查链接状态
|
||
/// </summary>
|
||
private async void DoConnect(int id)
|
||
{
|
||
await Task.Run(() =>
|
||
{
|
||
tools.Logging("站点" + id + "目前系统由于卫通/下位机原因链接断开,IP:" + Ipaddress + "端口号:" + Port + "开始重新连接");
|
||
IsDoConnect = true;
|
||
while (!IsOnline())
|
||
{
|
||
Thread.Sleep(15000);
|
||
if (id == 1)
|
||
MainWindow.mainViewModel.DoSocket1Connect("连接");
|
||
if (id == 2)
|
||
MainWindow.mainViewModel.DoSocket2Connect("连接");
|
||
Thread.Sleep(15000);
|
||
}
|
||
//如果连接成功则切出检查连接模式
|
||
tools.Logging("站点" + id + "目前系统由于卫通/下位机原因链接断开,IP:" + Ipaddress + "端口号:" + Port + "重新链接成功,退出重新链接模式");
|
||
IsDoConnect = false;
|
||
});
|
||
}
|
||
/// <summary>
|
||
/// 停止
|
||
/// </summary>
|
||
public override void Stop()
|
||
{
|
||
Sockets sks = new Sockets();
|
||
try
|
||
{
|
||
if (client != null)
|
||
{
|
||
client.Client.Shutdown(SocketShutdown.Both);
|
||
Thread.Sleep(10);
|
||
client.Close();
|
||
IsClose = true;
|
||
client = null;
|
||
}
|
||
else
|
||
{
|
||
sks.ex = new Exception("客户端没有初始化.!");
|
||
}
|
||
if (pushSockets != null)
|
||
pushSockets.Invoke(sks);//推送至UI
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
sks.ex = ex;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 发送消息
|
||
/// </summary>
|
||
public void SendData(byte[] SendData)
|
||
{
|
||
try
|
||
{
|
||
if (client == null || !client.Connected)
|
||
{
|
||
Sockets sks = new Sockets();
|
||
sks.ex = new Exception("客户端无连接..");
|
||
sks.ClientDispose = true;
|
||
if (pushSockets != null)
|
||
pushSockets.Invoke(sks);//推送至UI
|
||
}
|
||
if (client != null && client.Connected) //如果连接则发送
|
||
{
|
||
if (nStream == null)
|
||
{
|
||
nStream = client.GetStream();
|
||
}
|
||
nStream.Write(SendData, 0, SendData.Length);
|
||
}
|
||
}
|
||
catch (Exception skex)
|
||
{
|
||
Sockets sks = new Sockets();
|
||
sks.ex = skex;
|
||
sks.ClientDispose = true;
|
||
if (pushSockets != null)
|
||
pushSockets.Invoke(sks);//推送至UI
|
||
}
|
||
}
|
||
|
||
public bool Is_Connected()
|
||
{
|
||
return client.Connected;
|
||
}
|
||
|
||
public bool IsOnline()
|
||
{
|
||
if (client == null)
|
||
return false;
|
||
return !((client.Client.Poll(1000, SelectMode.SelectRead) && (client.Client.Available == 0)) || !client.Client.Connected);
|
||
}
|
||
}
|
||
}
|