简体   繁体   English

挂起Socket.Receive也不例外

[英]Hangs on Socket.Receive with no exception

I have WPF C# application that communicate with a PLC (ie write/read Omron PLC's memory addresses) through Ethernet (UDP packets) using FINS command/frame. 我有WPF C#应用程序,使用FINS命令/帧通过以太网(UDP数据包)与PLC通信(即写入/读取欧姆龙PLC的内存地址)。

I can send command to WRITE PLC address successfully, but application hangs/crashes when trying to get a responds from PLC during a READ command. 我可以成功地将命令发送到WRITE PLC地址,但是在READ命令期间尝试从PLC获得响应时,应用程序会挂起/崩溃。

FINS packet frame to be sent from PC to 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
};

Following code is my Socket send and receive: 以下代码是我的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;
}

I tried also to use Try-Catch , but no exception is caught during application hangs. 我也尝试使用Try-Catch ,但在应用程序挂起期间没有捕获异常。 I checked eventvwr , which says: 我检查了eventvwr ,其中说:

Souce: Application Hangs - "...stopped interacting with Windows and was closed" Detail : (screenshot below) Souce: Application Hangs - "...stopped interacting with Windows and was closed" 详情 :( (screenshot below)

在此输入图像描述

The reason why you're application hangs is obviously since your application is waiting forever to get data from the source. 您的应用程序挂起的原因显然是因为您的应用程序永远等待从源获取数据。 Its a good practice to schedule long running IO on a background thread or use the async versions of Send and receive. 在后台线程上安排长时间运行的IO或使用发送和接收的异步版本是一种很好的做法。 Your code contains a bug on the following lines: 您的代码包含以下行中的错误:

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

    totalBytesRcvd += bytesRcvd; 
} 

You are waiting for totalBytesRcvd to contain the amount of expected bytes, and you're updating it by adding the bytesRcvd data. 您正在等待totalBytesRcvd包含预期的字节数,并且您通过添加bytesRcvd数据来更新它。 Yet you never update bytesRcvd. 但你永远不会更新bytesRcvd。 You need to catch the return value of the call to sock.Receive in bytesRcvd. 你需要在bytesRcvd中捕获对sock.Receive的调用的返回值。 If this doesn't fix the problem, it will mean that there are either communication problems between the server and the client (note that you're using UDP so that might not be unreasonable)- or that the actual message is shorter in length than expected. 如果这不能解决问题,那就意味着服务器和客户端之间存在通信问题(请注意,您使用的UDP可能不合理) - 或者实际消息的长度短于预期。

I had the same problem, and found my solution was to check socket.Available before attempting to receive. 我有同样的问题,发现我的解决方案是检查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));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM