4

我有 WPF C# 应用程序,它使用 FINS 命令/帧通过以太网(UDP 数据包)与 PLC 通信(即写入/读取 Omron PLC 的内存地址)。

我可以成功地向WRITE PLC 地址发送命令,但是在READ命令期间尝试从 PLC 获取响应时应用程序挂起/崩溃。

要从 PC 发送到 PLC 的 FINS 数据包帧:

// Packets send to PLC to read Memory Address DM1000
byte[] sendPacket = new byte[]
{
    // 81 00 02 00 00 00 00 FF 00 19 01 01 82 00 64 00 00 01

    // FINS header
    0x81, //0.(ICF) Display frame information: 1000 0001 (Response required)
    0x00, //1.(RSV) Reserved by system: (hex)00
    0x02, //2.(GCT) Permissible number of gateways: (hex)02
    0x00, //3.(DNA) Destination network address: (hex)00, local network
    0x00, //4.(DA1) Destination node address: (hex)00, local PLC unit
    0x00, //5.(DA2) Destination unit address: (hex)00, PLC
    0x00, //6.(SNA) Source network address: (hex)00, local network
    0xFE, //7.(SA1) Source node address: (hex)05, PC's IP is 100.0.0.254
    0x00, //8.(SA2) Source unit address: (hex)00, PC only has one ethernet
    0x19, //9.(SID) Service ID: just give a random number 19

    // FINS command
    0x01, //10.(MRC) Main request code: 01, memory area read
    0x01, //11.(SRC) Sub-request code: 01, memory area read

    // Memory Area
    0x82, //12.Memory area code (1 byte): 82(DM)

    // Address information
    0x00, //13.Read start address (2 bytes): D100
    0x64, 
    0x00, //15.Bit address (1 byte): Default 0

    // Words read
    0x00, //16. Words read (2bytes)
    0x01
};

以下代码是我的 Socket 发送和接收:

sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sock.Connect(SERV_IP_ADDR, FINS_UDP_PORT);
sock.Send(sendPacket, 0, sendPacket.Length, SocketFlags.None);

int totalBytesRcvd = 0;     // Total bytes received so far
int bytesRcvd = 0;          // Bytes received in last read
while (totalBytesRcvd < sendPacket.Length)
{
    bytesRcvd = sock.Receive(sendPacket, totalBytesRcvd, sendPacket.Length - totalBytesRcvd, SocketFlags.None);
    if (bytesRcvd == 0)
    {
        MessageBox.Show("Connection closed prematurely.");
        break;
    }

    totalBytesRcvd += bytesRcvd;
}

我也尝试使用Try-Catch,但在应用程序挂起期间没有捕获到异常。我检查了eventvwr,上面写着:

来源: Application Hangs - "...stopped interacting with Windows and was closed" 详细信息(screenshot below)

在此处输入图像描述

4

2 回答 2

4

您的应用程序挂起的原因显然是因为您的应用程序一直在等待从源获取数据。在后台线程上安排长时间运行的 IO 或使用发送和接收的异步版本是一个很好的做法。您的代码包含以下几行的错误:

while (totalBytesRcvd < msg.Length) 
{ 
    // Application hangs right at the sock.Receive 
    sock.Receive(msg, totalBytesRcvd, msg.Length - totalBytesRcvd, SocketFlags.None); 

    totalBytesRcvd += bytesRcvd; 
} 

您正在等待 totalBytesRcvd 包含预期字节数,并且您正在通过添加 bytesRcvd 数据来更新它。然而你永远不会更新 bytesRcvd。您需要在 bytesRcvd 中捕获调用 sock.Receive 的返回值。如果这不能解决问题,则意味着服务器和客户端之间存在通信问题(请注意,您使用的是 UDP,因此这可能不是不合理的) - 或者实际消息的长度比预期的。

于 2012-03-29T03:46:04.890 回答
0

我遇到了同样的问题,发现我的解决方案是在尝试接收之前检查 socket.Available。

byte[] bytes = new byte[tcpClient.ReceiveBufferSize];

if (socket.Available > 0)
{
   int bytesRec = socket.Receive(bytes);
   Console.WriteLine("Echoed test = {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec));
}
于 2015-04-07T16:09:15.843 回答