工控机网络开发

在工控领域,用到网络的地方有两个,一是跟平台通信(把现场数据上传到平台、服务器),二是读取一些用网线连接的仪器。两个方面在使用Socket的时候,有某些需要注意的地方。

一、跟平台通信

跟平台通信使用TCP连接。如果工控机性能不错,使用DotNetty这样的库也未尝不可,毕竟其稳定性是经过验证的。但DotNetty开发成本高,现场也没有高并发的情况,大多时候我们都是使用Socket做简单的开发。在开发的过程中,我们会遇到几个问题:

(1)断网重连。

(2)超时时间。

(3)同步与异步接收数据。

1、断网重连

无论网络多好,都会有断开的时候,这就要求我们在网络断开之后,能自动识别,并再次连接服务器。

Socket使用下面的语句判断网络是否断开:

bool isConnected = !mSocket.Poll(1000, SelectMode.SelectRead);

2、超时时间

.NET里的Socket是没有连接超时设置功能的,如果在网络不通的情况下,一个连接会需要20s左右的等待时间,这样大多时候是不满足我们的期待的。

这里我们使用的辅助手段是这样的:在启动连接的时候,同时启动一个定时器。在定时器到点的时候,强制关闭正在进行的连接。虽然看起来不太优雅,但这已几乎是唯一的方法。

private void ConnectWithTimeout()
{
    mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    isInit = false;
    mTimeoutObject = new ManualResetEvent(false);

    try
    {
        mSocket.BeginConnect(mIPEndPoint, ConnectCallback, mSocket);
        if (!mTimeoutObject.WaitOne(WebTimeOut, false))
        {
            LogToFile.WriteWebExceptionLog("SocketHelper ConnectWithTimeout Timeout");

            CloseSocket();
        }
        else if (isInit)
        {
            mSocket.BeginReceive(DataBuffer, 0, DataBuffer.Length, 0, ReceiveCallback, mSocket);
        }
    }
    catch (Exception ex)
    {
        isInit = false;
        LogToFile.WriteWebExceptionLog("SocketHelper ConnectWithTimeout " + ex.Message);
    }
}

3、同步与异步接收数据

使用同步还是异步,这需要看具体的使用需求。使用同步的话,流程逻辑会简单一些,但需要卡住等待;而异步就不需要等待,但会让代码逻辑稍微复杂一些。

同步接收数据代码如下:

public byte[] Receive()
{
    try
    {
        int len = mSocket.Receive(DataBuffer);

        if (len > 0)
        {
            byte[] data = new byte[len];
            Array.Copy(DataBuffer, 0, data, 0, len);

            string dataStr = ConvertCode.ByteArrayToString(data, data.Length);
            LogToFile.WriteWebNormalLog("SocketHelper Receive: " + dataStr);

            return data;
        }
    }
    catch (Exception ex)
    {
        LogToFile.WriteWebExceptionLog("SocketHelper Receive " + ex.Message);
    }

    return null;
}

异步接收数据代码如下:

mSocket.BeginReceive(DataBuffer, 0, DataBuffer.Length, 0, ReceiveCallback, null);

private void ReceiveCallback(IAsyncResult ar)
{
    try
    {
        if (mSocket != null)
        {
            int len = mSocket.EndReceive(ar);
            if (len > 0)
            {
                byte[] data = new byte[len];
                Array.Copy(DataBuffer, 0, data, 0, len);

                string dataStr = ConvertCode.ByteArrayToString(data, data.Length);
                LogToFile.WriteWebNormalLog("SocketHelper Receive: " + dataStr);

                try
                {
                    ReceiveDataEvent(data);
                }
                catch (Exception ex)
                {
                    LogToFile.WriteWebExceptionLog("SocketHelper ReceiveCallback2 " + ex.Message);
                }
            }

            bool isConnected = !mSocket.Poll(1000, SelectMode.SelectRead);
            if (isConnected)
            {
                mSocket.BeginReceive(DataBuffer, 0, DataBuffer.Length, 0, ReceiveCallback, null);
            }
        }
    }
    catch (Exception ex)
    {
        LogToFile.WriteWebExceptionLog("SocketHelper ReceiveCallback " + ex.Message);
        isInit = false;

        CloseSocket();
    }
}

二、跟仪器通信

仪器各种各样,他们使用的通信方式也会千差万别。大多数情况下,仪器还是会使用TCP连接,但有的时候会使用UDP,甚至要求工控机作为服务端。

这里提出一点需要注意的,就是跟仪器连接的使用,一般不使用异步的方法,甚至只能使用同步的方法。有的仪器,用异步接收,会有连接不上的情况出现。因为仪器跟工控机的距离很短,连接也很稳定,所以使用同步的方法问题也不太,程序还能写得更简单一些。

同步接收数据:

/// <summary>
/// 同步接收数据
/// </summary>
/// <returns>接收到的数据</returns>
public byte[] Receive()
{
    try
    {
        int len = mSocket.Receive(DataBuffer);

        if (len > 0)
        {
            byte[] data = new byte[len];
            Array.Copy(DataBuffer, 0, data, 0, len);

            string dataStr = ConvertCode.ByteArrayToString(data, data.Length);
            LogToFile.WriteWebNormalLog("DeviceSocketHelper Receive: " + dataStr);

            return data;
        }
    }
    catch (Exception ex)
    {
        LogToFile.WriteWebExceptionLog("DeviceSocketHelper Receive " + ex.Message);
    }

    return null;
}

几个类库的源代码下载:https://download.csdn.net/download/lweiyue/10648659

猜你喜欢

转载自blog.csdn.net/lweiyue/article/details/82453645