Pregunta

I have WPF C# application that communicate with a PLC (i.e. write/read Omron PLC's memory addresses) through Ethernet (UDP packets) using FINS command/frame.

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.

FINS packet frame to be sent from PC to PLC:

// 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:

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. I checked eventvwr, which says:

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

enter image description here

¿Fue útil?

Solución

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. 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. Yet you never update bytesRcvd. You need to catch the return value of the call to sock.Receive in bytesRcvd. 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.

Otros consejos

I had the same problem, and found my solution was to check socket.Available before attempting to receive.

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));
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top