using System;
using System.Net;
using System.Net.Sockets;
using System.IO.Ports;
using System.Threading;
using System.Text;
using System.IO;
using System.Windows.Forms;
namespace TCP2COM
{
/// <summary>
/// 数据转发代理
/// </summary>
/// <param name="reDatas">接受数据</param>
/// <param name="length">数据长度</param>
public delegate void DataArriveEventHandler( DataArraveArgs e);
/// <summary>
/// 通信设备连接代理
/// </summary>
/// <param name="status">连接状态</param>
public delegate void ConStateEvetnHandler(bool status,string msg,CommType type);
public enum CommType
{
/// <summary>
/// 串口 通信
/// </summary>
COM = 0,
/// <summary>
/// Socket通信
/// </summary>
TCP = 1,
/// <summary>
/// 其它
/// </summary>
OTHER=2
}
public class DataArraveArgs : EventArgs
{
private byte[] reDatas;
private int dataLen;
private CommType type;
public byte[] ReDatas
{
get { return reDatas; }
}
public int DataLen
{
get { return dataLen; }
}
public CommType Type
{
get { return type; }
}
public DataArraveArgs(ref byte[] reDatas, int dataLen,CommType type)
{
this.reDatas = reDatas;
this.dataLen = dataLen;
this.type = type;
}
}
public class ConStateArgs : EventArgs
{
public bool status;
public string msg;
public CommType type;
public ConStateArgs(bool status, string msg, CommType type)
{
this.status = status;
}
}
public class ClientInfo
{
private const int BUFFERSIZE = 1024;
private byte[] buffers = new byte[BUFFERSIZE];
private int dataLen;
public byte[] Buffers
{
get { return buffers; }
set
{
buffers = value;
}
}
public int DataLen
{
get { return dataLen; }
set
{
if (dataLen!= value)
{
dataLen = value;
}
}
}
}
public class Commun
{
public event DataArriveEventHandler OnDataArrive;//声明一个EvenDataArriveHandler委托类型的事件
public event ConStateEvetnHandler ConState;
private int port;
private string serverIP;
private string comNum;
private int baudRate;
private Socket mainSocket;
private SerialPort mainPort;
private bool status = false;
private string msg = string.Empty;
private int waitTime=50;
private bool uncheckPort=true,uncheckSocket =true;
private bool comEdit;
public bool Status
{
get { return status; }
}
private byte[] ErrorBuffers;
public bool PortStatus
{
get { return mainPort.IsOpen; }
}
public bool UNCheckPort
{
set
{
uncheckPort = value;
}
}
public bool UnCheckSocket
{
set { uncheckSocket = value; }
}
public int WaritTime
{
set
{
if (waitTime != value)
{
waitTime = value;
}
}
}
public string ServerIP
{
get { return serverIP; }
set
{
if (serverIP != value)
{
serverIP = value;
}
}
}
public int Port
{
get { return port; }
set
{
if (port != value)
{
port =value;
}
}
}
public string ComNum
{
get { return mainPort.PortName; }
set
{
if (comNum != value)
{
comEdit = true;
comNum = value;
}
else
{
comEdit = comEdit | false;
}
}
}
public int BaudRate
{
get { return mainPort.BaudRate; }
set
{
if (baudRate != value)
{
comEdit = true;
baudRate = value;
}
else
{
comEdit = comEdit | false;
}
}
}
private ClientInfo portInfo = new ClientInfo();
private ClientInfo socketInfo = new ClientInfo();
public Commun()
{
mainPort = new SerialPort();
mainPort.DataReceived += new SerialDataReceivedEventHandler(mainPort_DataReceived);
}
void mainPort_DataReceived(object sender,
SerialDataReceivedEventArgs e)
{
Array.Clear(portInfo.Buffers, 0, portInfo.DataLen);
portInfo.DataLen = 0;
try
{
int dataLen = mainPort.BytesToRead;
if (dataLen == 0)
{
return;
}
while (dataLen > 0)
{
portInfo.DataLen += mainPort.Read(portInfo.Buffers,
portInfo.DataLen, dataLen);
Thread.Sleep(waitTime);
dataLen = mainPort.BytesToRead;
}
if (CheckPack(portInfo.Buffers, portInfo.DataLen))
{
byte[] buffers = new byte[portInfo.DataLen];
Array.Copy(portInfo.Buffers, 0, buffers, 0, portInfo.DataLen);
OnDataArrive(new DataArraveArgs(ref buffers,
portInfo.DataLen, CommType.COM));
SendSocket(buffers);
}
else
{
SendPort(ErrorBuffers);
}
}
catch (Exception exp)
{
#if DEBUG
WriteLine(exp, "串口数据接受");
#endif
}
}
public void Connection(object sender,EventArgs e)
{
try
{
if (comEdit)
{
if (mainPort.IsOpen)
{
mainPort.Close();
}
mainPort.PortName = comNum;
mainPort.BaudRate = baudRate;
mainPort.Open();
}
else
{
if (!mainPort.IsOpen)
{
mainPort.PortName = comNum;
mainPort.BaudRate = baudRate;
mainPort.Open();
}
}
status = mainPort.IsOpen;
}
catch (Exception exp)
{
status = false;
msg = exp.Message;
#if DEBUG
WriteLine(exp, "打开串口");
#endif
}
finally
{
if (ConState != null)
{
ConState(status, msg, CommType.COM);
}
comEdit = false;
BeginConnection();
}
}
private void BeginConnection()
{
mainSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
try
{
IPAddress ip = Dns.GetHostEntry(serverIP).AddressList[0];
mainSocket.BeginConnect(ip, port, new AsyncCallback(EndConnection), mainSocket);
}
catch(Exception exp)
{
Close(exp, CommType.TCP);
#if DEBUG
WriteLine(exp, "Socket 异步连接");
#endif
}
}
public void Close(Exception exp, CommType type)
{
if (mainPort.IsOpen)
{
try
{
mainPort.Close();
}
catch (Exception error)
{
#if DEBUG
WriteLine(error, "关闭串口");
#endif
}
}
try
{
if (mainSocket.Connected)
{
mainSocket.Send(Encoding.Default.GetBytes("CLIENTEXIT"));
}
}
finally
{
mainSocket.Close();
if (ConState != null)
{
ConState(false, exp.Message, type);
}
}
}
public void Close()
{
if (mainPort.IsOpen)
{
try
{
mainPort.Close();
}
catch(Exception exp)
{
#if DEBUG
WriteLine(exp, "关闭串口");
#endif
}
}
try
{
if (mainSocket.Connected)
{
mainSocket.Send(Encoding.Default.GetBytes("CLIENTEXIT"));
}
}
finally
{
if (ConState != null && mainSocket.Connected)
{
ConState(false, "释放Socket资源", CommType.TCP);
mainSocket.Close();
}
}
}
private void EndConnection(IAsyncResult ar)
{
Socket socket = ar.AsyncState as Socket;
try
{
socket.EndConnect(ar);
status = socket.Connected;
}
catch (ObjectDisposedException)
{
status = false;
msg = "Socket对象已释放";
#if DEBUG
WriteLine(new Exception("已释放了Socket对象"), "数据接受处理");
#endif
}
catch (SocketException exp)
{
status = false;
if (exp.ErrorCode.Equals(10060))
{
msg = "服务器长时间无响应";
}
else if (exp.ErrorCode.Equals(10061))
{
msg = "服务器未开启";
}
else
{
msg = "套接字错误引发异常";
}
#if DEBUG
WriteLine(new Exception("套接字错误引发异常"), "数据接受处理");
#endif
}
catch (Exception)
{
msg = "Socket异步连接错误";
status = false;
#if DEBUG
WriteLine(new Exception("Socket异步连接错误"), "Socket 连接EndConnection");
#endif
}
finally
{
if (ConState != null)
{
ConState(status, msg, CommType.TCP);
}
if (status)
{
BeginReceive();
}
}
}
private void BeginReceive()
{
if (mainSocket.Connected)
{
try
{
Array.Clear(socketInfo.Buffers, 0, socketInfo.DataLen);
socketInfo.DataLen = 0;
mainSocket.BeginReceive(socketInfo.Buffers, 0, 1024,
SocketFlags.None, new AsyncCallback(EndReceive), null);
}
catch (ObjectDisposedException)
{
status = false;
Close(new Exception("服务器已释放了Socket对象"), CommType.TCP);
#if DEBUG
WriteLine(new Exception("服务器已释放了Socket对象"), "数据接受处理");
#endif
}
catch (SocketException)
{
status = false;
Close(new Exception("服务器已放弃了一个连接"), CommType.TCP);
#if DEBUG
WriteLine(new Exception("服务器已放弃了一个连接"), "数据接受处理");
#endif
}
catch (Exception)
{
status = false;
if (ConState != null)
{
ConState(status, "Socket开始接受数据错误", CommType.TCP);
}
#if DEBUG
WriteLine(new Exception("Socket开始接受数据错误"), "异步接受数据");
#endif
}
}
}
private void EndReceive(IAsyncResult ar)
{
try
{
if (!mainSocket.Connected)
{
mainSocket.Close();
return;
}
socketInfo.DataLen = mainSocket.EndReceive(ar);
if (socketInfo.DataLen == 0)
{
mainSocket.Send(Encoding.Default.GetBytes("HZKJ"));
BeginReceive();
return;
}
if (Encoding.Default.GetString(socketInfo.Buffers, 0,
socketInfo.DataLen) == "SERVERSTOP")
{
status = false;
if (ConState != null)
{
ConState(status, "服务器主动断开", CommType.TCP);
}
Close();
}
ErrorBuffers = new byte[socketInfo.DataLen];
Array.Copy(socketInfo.Buffers, 0, ErrorBuffers, 0, socketInfo.DataLen);
OnDataArrive(new DataArraveArgs(ref ErrorBuffers,
socketInfo.DataLen, CommType.TCP));
SendPort(ErrorBuffers);
BeginReceive();
}
catch (ObjectDisposedException)
{
status = false;
Close(new Exception("服务器已释放了Socket对象"), CommType.TCP);
#if DEBUG
WriteLine(new Exception("服务器已释放了Socket对象"), "数据接受处理");
#endif
}
catch (SocketException)
{
status = false;
Close(new Exception("服务器已放弃了一个连接"), CommType.TCP);
#if DEBUG
WriteLine(new Exception("服务器已放弃了一个连接"), "数据接受处理");
#endif
}
catch (Exception)
{
status = false;
Close(new Exception("Socket接受错误"), CommType.TCP);
#if DEBUG
WriteLine(new Exception("Socket消息接受错误"), "数据接受处理");
#endif
}
}
public void SendPort(byte[] sDatas)
{
try
{
mainPort.Write(sDatas, 0, sDatas.Length);
}
catch(Exception exp)
{
try
{
if (mainPort.IsOpen)
{
mainPort.Close();
}
}
catch
{
#if DEBUG
WriteLine(exp, "串口发送数据||打开");
#endif
}
finally
{
if (ConState != null)
{
ConState(false, exp.Message, CommType.COM);
}
}
}
}
public void SendSocket(byte[] sDatas)
{
try
{
mainSocket.Send(sDatas);
}
catch (ObjectDisposedException)
{
status = false;
Close(new Exception("服务器已释放了Socket对象"), CommType.TCP);
#if DEBUG
WriteLine(new Exception("服务器已释放了Socket对象"), "数据接受处理");
#endif
}
catch (SocketException)
{
status = false;
Close(new Exception("套接字错误引发异常"), CommType.TCP);
#if DEBUG
WriteLine(new Exception("套接字错误引发异常"), "数据接受处理");
#endif
}
catch (Exception)
{
if (ConState != null)
{
ConState(false, "Socket消息发送错误", CommType.TCP);
}
#if DEBUG
WriteLine(new Exception("Socket消息发送错误"), "Scoket 数据发送");
#endif
}
}
public bool Send(string msg, bool com)
{
string[] msgs = msg.Split(' ');
byte[] buffers = new byte[msgs.Length];
if (msgs.Length > 1)
{
try
{
for (int i = 0; i < msgs.Length; i++)
{
buffers[i] = Convert.ToByte(msgs[i], 16);
}
if (!CheckPack(buffers, msgs.Length)) return false;
}
catch (Exception) { }
}
else
{
buffers = Encoding.Default.GetBytes(msg);
}
if (com)
{
if (!mainPort.IsOpen)
{
msg = string.Empty;
try
{
mainPort.Open();
}
catch (Exception exp)
{
msg = "当前串口已占用|不存在";
#if DEBUG
WriteLine(exp, "串口打开");
#endif
}
finally
{
if (ConState != null)
{
ConState(mainPort.IsOpen, msg, CommType.COM);
}
}
}
SendPort(buffers);
}
else
{
if (!mainSocket.Connected)
{
BeginConnection();
}
SendSocket( buffers);
}
return true;
}
/// <summary>
/// 函数功能:校验和
/// 函数名称: VadateDatas
/// 参 数: byte[] reDatas,int dataLen
/// 返 回 值: bool
/// 程 序 员: XLG
/// 编制日期: 08/06/02
/// 函数说明:
/// 1, 对接受的数据进行校验
/// 2,校验启动位,停止位,偶校验位
/// </summary>
private bool CheckPack(byte[] reDatas, int dataLen)
{
if (reDatas[0] == 0xAA && dataLen == 14)
{
return true;
}
if (reDatas[0] != 0x68 || reDatas[5] != 0x68)
{
return false;
}
else if (reDatas[12].Equals(0x20))
{
return true;
}
else if (dataLen < 0x10)
{
return false;
}
else if (!CheckPack(ref reDatas))
{
return false;
}
else
{
return true;
}
}
/// <summary>
/// 函数功能:校验接受数据长度和验证校验和
/// 函数名称: CheckPack
/// 参 数:
/// 返 回 值: static void
/// 程 序 员: XLG
/// 编制日期: 08/06/02
/// 函数说明:
/// 1, 按照规约验证校验和,数组长度
/// </summary>
private bool CheckPack(ref byte[] reDatas)
{
short LA, LB, L;
LA = reDatas[2];
LA = Convert.ToInt16(LA << 8 | reDatas[1]);
LB = reDatas[4];
LB = Convert.ToInt16(LB << 8 | reDatas[3]);
if (LA != LB)
{
return false;
}
L = Convert.ToInt16(LA >> 2);
byte CS = 0;
for (int i = 6; i <= L + 5; i++)
{
CS += reDatas[i];
}
if (CS == reDatas[L + 6])
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// Debug测试异常
/// </summary>
/// <param name="exp"></param>
/// <param name="msg"></param>
public static void WriteLine(Exception exp, string msg)
{
string file = Application.StartupPath + @"\Debug.ini";
try
{
using (StreamWriter sw = new StreamWriter(file, true))
{
string message = new string('*', 20);
sw.WriteLine("{0}〓{1}〓{2}", message, msg, message);
sw.WriteLine("Message:{0}", exp.Message);
sw.WriteLine("Source:{0}", exp.Source);
sw.WriteLine("StackTrace:{0}", exp.StackTrace);
sw.WriteLine("{0}〓{1}〓{2}", message, DateTime.Now, message);
}
System.Diagnostics.Trace.WriteLine(exp.Message);
}
catch
{ ;}
}
}
}