康耐德C2000设备可配置作为客户端和服务端两种方式,本次介绍的是将其作为服务端(采用服务端的好处是采集器开关量主动推送给已建立连接的客户端,客户端只需建立一个长连接,实时监测服务端是否发送开关量数据过来)进行通信,通信方式采用TCP/IP协议,通过康耐德官方的【C2000设备管理监控工作站】进行设备的IP,port等配置即可建立通信。
客户端与服务端(C2000)通信的相关主要代码附上
- 因为是多台设备所以采用多线程分开运作,互不干涉
private void OpenC2000Connect()
{
try
{
ThreadForC2000_topStitchLine = new Thread(C2000DriveFor_topStitchLine);
ThreadForC2000_topStitchLine.IsBackground = true;
ThreadForC2000_getOffLine = new Thread(C2000DriveFor_getOffLine);
ThreadForC2000_getOffLine.IsBackground = true;
ThreadForC2000_assemblyLine = new Thread(C2000DriveFor_assemblyLine);
ThreadForC2000_assemblyLine.IsBackground = true;
ThreadForC2000_topStitchLine.Start();
ThreadForC2000_getOffLine.Start();
ThreadForC2000_assemblyLine.Start();
}
catch
{
throw;
}
}
- 初始化Socket链接
private void Initialize_topStitchLineC2000()
{
try
{
IPAddress ip = IPAddress.Parse(C2000_topStitchLineIP);
var ipe = new IPEndPoint(ip, port);
SocketFor_topStitchLine.Connect(ipe);
SocketFor_topStitchLine.BeginReceive(RecieveFor_topStitchLine, 0, RecieveFor_topStitchLine.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack_topStitchLine), null);
}
catch
{
throw;
}
}
private void Initialize_getOffLineC2000()
{
try
{
IPAddress ip = IPAddress.Parse(C2000_getOffLineIP);
var ipe = new IPEndPoint(ip, port);
SocketFor_getOffLine.Connect(ipe);
SocketFor_getOffLine.BeginReceive(RecieveFor_getOffLine, 0, RecieveFor_getOffLine.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack_getOffLine), null);
}
catch
{
throw;
}
}
private void Initialize_assemblyLineC2000()
{
try
{
IPAddress ip = IPAddress.Parse(C2000_assemblyLineIP);
var ipe = new IPEndPoint(ip, port);
SocketFor_assemblyLine.Connect(ipe);
SocketFor_assemblyLine.BeginReceive(RecieveFor_assemblyLine, 0, RecieveFor_assemblyLine.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack_assemblyLine), null);
}
catch
{
throw;
}
}
- 异步监视服务端返回值
private void ReceiveCallBack_topStitchLine(IAsyncResult IAR)
{
try
{
int REnd = SocketFor_topStitchLine.EndReceive(IAR);
var cmd = RecieveFor_topStitchLine.ConvertToHexStringFromHexByte(REnd);
var state = BLL.Common.Setting.RunningState.runing;
if (cmd == DataSetCache.C2000_CMD.D1_runing ||
cmd == DataSetCache.C2000_CMD.D1D2D2_runing)
state = BLL.Common.Setting.RunningState.runing;
if (cmd == DataSetCache.C2000_CMD.D1D2 ||
cmd == DataSetCache.C2000_CMD.D1D2D1 ||
cmd == DataSetCache.C2000_CMD.D2)
state = BLL.Common.Setting.RunningState.fault;
if (cmd == DataSetCache.C2000_CMD.D1Off)
state = BLL.Common.Setting.RunningState.stop;
DataSetCache.Services.TopStitchInsert(state);
SocketFor_topStitchLine.BeginReceive(RecieveFor_topStitchLine, 0, RecieveFor_topStitchLine.Length, 0, new AsyncCallback(ReceiveCallBack_topStitchLine), null);
}
catch (Exception ex)
{
Logger.Error(ex.Message);
}
}
private void ReceiveCallBack_getOffLine(IAsyncResult IAR)
{
try
{
int REnd = SocketFor_getOffLine.EndReceive(IAR);
var cmd = RecieveFor_getOffLine.ConvertToHexStringFromHexByte(REnd);
var state = BLL.Common.Setting.RunningState.runing;
if (cmd == DataSetCache.C2000_CMD.D1_runing ||
cmd == DataSetCache.C2000_CMD.D1D2D2_runing)
state = BLL.Common.Setting.RunningState.runing;
if (cmd == DataSetCache.C2000_CMD.D1D2 ||
cmd == DataSetCache.C2000_CMD.D1D2D1 ||
cmd == DataSetCache.C2000_CMD.D2)
state = BLL.Common.Setting.RunningState.fault;
if (cmd == DataSetCache.C2000_CMD.D1Off)
state = BLL.Common.Setting.RunningState.stop;
DataSetCache.Services.GetOffLineInsert(state);
SocketFor_getOffLine.BeginReceive(RecieveFor_getOffLine, 0, RecieveFor_getOffLine.Length, 0, new AsyncCallback(ReceiveCallBack_getOffLine), null);
}
catch (Exception ex)
{
Logger.Error(ex.Message);
}
}
private void ReceiveCallBack_assemblyLine(IAsyncResult IAR)
{
try
{
int REnd = SocketFor_assemblyLine.EndReceive(IAR);
var cmd = RecieveFor_assemblyLine.ConvertToHexStringFromHexByte(REnd);
var state = BLL.Common.Setting.RunningState.runing;
if (cmd == DataSetCache.C2000_CMD.D1_runing ||
cmd == DataSetCache.C2000_CMD.D1D2D2_runing)
state = BLL.Common.Setting.RunningState.runing;
if (cmd == DataSetCache.C2000_CMD.D1D2 ||
cmd == DataSetCache.C2000_CMD.D1D2D1 ||
cmd == DataSetCache.C2000_CMD.D2)
state = BLL.Common.Setting.RunningState.fault;
if (cmd == DataSetCache.C2000_CMD.D1Off)
state = BLL.Common.Setting.RunningState.stop;
DataSetCache.Services.AssemblyLineInsert(state);
SocketFor_assemblyLine.BeginReceive(RecieveFor_assemblyLine, 0, RecieveFor_assemblyLine.Length, 0, new AsyncCallback(ReceiveCallBack_assemblyLine), null);
}
catch (Exception ex)
{
Logger.Error(ex.Message);
}
}
在开发客户端通信的过程中碰到几点问题,在这里把遇到的问题以及解决方案介绍下:
- 因客户端安装在服务器上,设备安装在现场,现场下班就会断电,服务器是不会关机的,这就导致当现场断电采集器(服务端),第二天开机是,和客户端已经建立的连接客户端还记得,但是服务端已经不记得啦。客户端这个时候就很尴尬,连接不上服务端, 重连又告诉你,你已经有连接啦。怎么办?
解:
public void C2000Drive()
{
while (true)
{
try
{
if (C2000IP.PingIp())
{
if (!SocketForLine.Connected)
InitializeLineC2000();
timerC2000Line();
}
else
{
if (SocketForLine.Connected)
{
SocketForLine.Close();
SocketForLine = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
} lbl_C2000Line.Image = Resources.black;
} Thread.Sleep(5000);
}
catch (Exception ex)
{
Logger.Error(ex.Message);
}
}
}
当服务端IP地址ping不同的时候,并且Socket连接仍然是Connected状态(不主动关闭,即使服务端断了,连接状态还是Connected,我擦,网都不通啦,还连接个啥啊)的情况下,手动关闭连接并重新实例化Socket对象.
|