using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Module.Socket.Tool
{
public class TcpClientChargerTool
{
#region 定义锁
private object lockObj = new object(); //线程同步锁
#endregion 定义锁
TcpClient ClientTcp = new TcpClient();
NetworkStream ClientStream = null;
private readonly object LockHandler = new object();
///
/// 确定的已接收缓存字节数组
///
private byte[] FixedBuffer;
///
/// 上次接收剩余字节
///
private List RemainBuffer = new List();
///
/// 缓存字节长度
///
private int BufferSize;
///
/// 客户端是否已经连接
///
private bool IsConnected = false;
private Thread DataMonitoringThread = null;
private Thread ConnectMonitoringThread = null;
public event EventHandler ConnectedStatusChanged;
public event EventHandler DataReceived;
public event EventHandler DataSended;
private string _client_ip;
///
/// 客户端IP地址
///
public string F_ClientIP
{
get
{
return _client_ip;
}
set
{
lock (lockObj)
{
_client_ip = value;
}
}
}
private int _client_port;
///
/// 客户端端口号
///
public int F_ClientPort
{
get
{
return _client_port;
}
set
{
lock (lockObj)
{
_client_port = value;
}
}
}
///
/// 客户端任务线程是否已经开始运行
///
public bool RaskThreadIsStart { get; set; } = true;
///
/// 数据接收事件是否被阻塞
///
public bool DataReceivedEventIsSuspend { get; set; } = false;
///
/// 读数据超时时间(毫秒)
///
public int ReadTimeout { get; set; } = 1000;
public TcpClientChargerTool() { }
public TcpClientChargerTool(string ipAddr, int port)
{
_client_ip = ipAddr;
_client_port = port;
}
///
/// 客户端连接
///
public virtual void ClientConnect()
{
try
{
Disconnect();
ClientTcp.Connect(_client_ip, _client_port);
ClientStream = ClientTcp.GetStream();
bool state = ClientTcp.Connected;
if (state == false)
{
IsConnected = false;
SetConnectStatusEvent("连接失败");
TerminateThreadsTCPStream();
}
else
{
IsConnected = true;
SetConnectStatusEvent("连接成功");
BufferSize = ClientTcp.ReceiveBufferSize;
FixedBuffer = new byte[BufferSize];
RaskThreadIsStart = true;
}
ConnectMonitoringThread = new Thread(MonitorConnecting);
ConnectMonitoringThread.Name = "TCP客户端连接状态监测" + _client_port.ToString();
ConnectMonitoringThread.Start();
DataMonitoringThread = new Thread(MonitorRecevingData);
DataMonitoringThread.Name = "TCP客户端数据接收监测" + _client_port.ToString();
DataMonitoringThread.Start();
}
catch (Exception ex)
{
SetConnectStatusEvent("连接失败" + ex.ToString());
}
}
///
/// 设置连接状态字符串
///
/// 连接状态字符串。比如:“连接成功”
private void SetConnectStatusEvent(string status)
{
string strClient = "";
if (ClientTcp != null && ClientTcp.Client.LocalEndPoint != null)
{
strClient = ClientTcp.Client.LocalEndPoint.ToString();
}
string strTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " ";
string strConnectLog = strTime + "客户端" + strClient + "与服务端" + _client_ip.ToString() + ":" + _client_port.ToString() + " " + status + "!";
EventHandler ConnectedHandler;
ConnectedHandler = ConnectedStatusChanged;
if (ConnectedHandler != null)
{
ConnectedHandler.Invoke(this, new ViewLogEventArgs() { ConnectedStatus = IsConnected, IsContent = strConnectLog });
}
}
///
/// 是否连接
///
public bool Connected
{
get
{
bool state = ClientTcp.Connected;
if (state == false)
{
TerminateThreadsTCPStream();
}
if (state != IsConnected)
{
IsConnected = state;
}
return state;
}
private set
{
if (value == IsConnected) return;
IsConnected = value;
}
}
///
/// 断开连接
///
public virtual void Disconnect()
{
TerminateThreadsTCPStream();
Connected = false;
ClientTcp.Close();
//ClientTcp.Dispose();
ClientTcp = new System.Net.Sockets.TcpClient();
//SetConnectStatusEvent("连接断开成功!");
}
///
/// 结束线程与数据流
///
private void TerminateThreadsTCPStream()
{
RaskThreadIsStart = false;
DataMonitoringThread = null;
ConnectMonitoringThread = null;
ClientStream?.Close();
ClientStream = null;
}
///
/// 获取客户端连接状态
///
///
private bool GetConnectedStatus()
{
return !((ClientTcp.Client.Poll(1000, SelectMode.SelectRead) && (ClientTcp.Client.Available == 0)) || !ClientTcp.Client.Connected);
}
///
/// 监测接收数据字符串
///
private async void MonitorRecevingData()
{
await Task.Run(() =>
{
try
{
EventHandler DataReceivedHandler;
while (RaskThreadIsStart)
{
if (!Connected) ClientConnect();
else
{
DataReceivedHandler = DataReceived;
if (DataReceivedHandler != null)
{
if (ClientStream != null)
{
if (ClientStream.DataAvailable)
{
lock (LockHandler)
{
List datas = ReadOrigBytes();
if (datas != null)
{
if (datas.Count > 0)
{
for (int i = 0; i < datas.Count; i++)
{
if (datas[i].Length > 0)
{
DataReceivedHandler.Invoke(this, new TcpDataReceivedEventArgs() { Data = datas[i] });
}
else
{
Thread.Sleep(2);
continue;
}
}
}
else
{
Thread.Sleep(2);
continue;
}
}
else
{
Thread.Sleep(2);
continue;
}
}
}
else
{
Thread.Sleep(2);
continue;
}
}
else
{
Thread.Sleep(2);
continue;
}
}
else
{
Thread.Sleep(2);
continue;
}
}
}
}
catch (Exception ex)
{
ex.ToString();
}
});
}
///
/// 读原始数据字节数组--解析成数组类型的数据帧格式
///
///
private List ReadOrigBytes()
{
List bytesResult = new List();
if (ClientStream != null)
{
ClientStream.ReadTimeout = ReadTimeout;
while (true)
{
int readByte = 0;
try
{
readByte = ClientStream.Read(FixedBuffer, 0, BufferSize);
if (readByte == 0) break;
else if (readByte >= 9)
{
bytesResult = GetReadResult(FixedBuffer, readByte);
}
if (!ClientStream.DataAvailable) break;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("警告: ReadRawBytes()引发异常: " + ex);
return null;
}
}
}
return bytesResult;
}
///
/// 监测客户端连接
///
private void MonitorConnecting()
{
while (RaskThreadIsStart)
{
bool state = Connected;
if (state != IsConnected)
{
IsConnected = state;
if (state == false)
{
SetConnectStatusEvent("连接失败");
TerminateThreadsTCPStream();
}
else
{
SetConnectStatusEvent("连接成功");
BufferSize = ClientTcp.ReceiveBufferSize;
FixedBuffer = new byte[BufferSize];
RaskThreadIsStart = true;
}
}
Thread.Sleep(20);
}
}
public bool checksumDomainReceive(byte[] data)
{
bool bResult = false;
int checksum = 0;
for (int i = 6; i < data.Count() - 1; i++)//这里有校验域所以减一
{
checksum += data[i];
}
//foreach (byte b in data)
//{
// checksum += b;
//}
// 取校验和的低8位
byte b1 = (byte)(checksum & 0xFF);
byte b2 = data[data.Count() - 1];
if (data[data.Count() - 1] == (byte)(checksum & 0xFF))
bResult = true;
return bResult;
}
private List GetReadResult(byte[] bytes, int readLen)
{
List lstResult = new List();
{
byte[] bytesCppy = bytes;//操作此数组,不要动原始数组
//自定义解析 起始0xAA 0XF5-----会有很多包粘连到一起的情况
{
if (readLen >= 9)
{
for (int i = 0; i < readLen; i++)
{
if (i + 1 <= readLen)
{
if (bytes[i] == 0xAA && bytes[i + 1] == 0xF5)
{
if (i + 2 < readLen)
{
int leng = ToUInt16(bytesCppy, i + 2);//帧的长度
// 创建一个新的byte数组来存储截取的数据
byte[] newBytes = new byte[leng];
// 使用Array.Copy方法将原始数组中的一部分复制到新数组
Array.Copy(bytesCppy, i, newBytes, 0, leng);
//校验域是否正确
if (checksumDomainReceive(newBytes))
{
var info = newBytes[4];
if ((info & (1 << 1)) != 0)//AES加密
{
List byteList = newBytes.ToList();
byteList.Remove(8);
byteList.Remove(8);//移除前面两个长度
newBytes= byteList.ToArray();
lstResult.Add(newBytes);
}
else //不加密
{
lstResult.Add(newBytes);
}
}
}
}
}
}
}
}
}
{
//int indexValue = 0;
//List lstStartIndex = new List(); //搜索开始字节0x68的索引值
//int len = 0;
//if (readLen >= 24)
//{
// for (int i = 0; i < readLen; i++)
// {
// if (bytes[i] == 0x68)
// {
// lstStartIndex.Add(i);
// }
// }
//}
//int indexNum = lstStartIndex.Count;
//if (indexNum > 0)
//{
// for (int j = 0; j < indexNum; j++)
// {
// indexValue = lstStartIndex[j];
// if (indexValue < bytes.Count())
// {
// if (j < indexNum - 1)
// {
// int datalen = lstStartIndex[j + 1] - lstStartIndex[j];
// //if (len == datalen)
// //{
// // indexValue += len;
// // byte[] data = new byte[datalen];
// // Array.Copy(bytes, lstStartIndex[j], data, 0, datalen);
// // lstResult.Add(data);
// //}
// //else
// //{
// // indexValue += len;
// // byte[] data = new byte[len];
// // if (len <= bytes.Count())
// // {
// // Array.Copy(bytes, lstStartIndex[j], data, 0, len);
// // lstResult.Add(data);
// // }
// //}
// byte[] data = new byte[datalen];
// if (len <= bytes.Count())
// {
// Array.Copy(bytes, lstStartIndex[j], data, 0, datalen);
// lstResult.Add(data);
// }
// }
// else
// {
// int datalen = readLen - lstStartIndex[j];
// byte[] data = new byte[datalen];
// Array.Copy(bytes, lstStartIndex[j], data, 0, datalen);
// lstResult.Add(data);
// }
// }
// }
//}
}
return lstResult;
}
/////
///// 客户端读字节
/////
///// 字节数组
//public List ReadBytes()
//{
// lock (LockHandler)
// {
// if (!Connected) ClientConnect();
// return ReadOrigBytes();
// }
//}
///
/// 客户端写字节指令
///
///
public void Write(byte[] dataBytes)
{
if (ClientTcp != null)
{
if (ClientTcp.Connected)
{
try
{
if (DataSended != null)
{
EventHandler DataSendHandler;
DataSendHandler = DataSended;
DataSendHandler.Invoke(this, new TcpDataSendEventArgs() { Data = dataBytes });
}
ClientStream.Write(dataBytes, 0, dataBytes.Length);
ClientStream.Flush();
}
catch (Exception ex)
{
ex.ToString();
}
}
}
}
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
TerminateThreadsTCPStream();
ClientTcp.Close();
ClientTcp = null;
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
private ushort ToUInt16(byte[] value, int offset)
{
return (ushort)(value[offset] + (value[offset + 1] << 8));
}
}
}