c# sockets udp plc fins

c# - Se bloquea en Socket.Receive sin excepción



sockets udp (2)

Tengo la aplicación WPF C # que se comunica con un PLC (es decir, escribe / lee las direcciones de memoria del PLC de Omron) a través de Ethernet (paquetes UDP) usando el comando / cuadro FINS.

Puedo enviar comandos para ESCRIBIR la dirección del PLC con éxito, pero la aplicación se cuelga / se bloquea al intentar recibir respuestas del PLC durante un comando de LECTURA .

Marco de paquete de FINS que se enviará de la PC al 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 };

El siguiente código es mi socket enviar y recibir:

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; }

Intenté también usar Try-Catch , pero no se detecta ninguna excepción durante la suspensión de la aplicación. Revisé eventvwr , que dice:

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


La razón por la cual su aplicación se cuelga es, obviamente, ya que su aplicación está esperando por siempre para obtener datos de la fuente. Es una buena práctica programar un IO de larga ejecución en un hilo de fondo o usar las versiones asíncronas de Enviar y recibir. Tu código contiene un error en las siguientes líneas:

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

Está esperando que totalBytesRcvd contenga la cantidad de bytes esperados y lo está actualizando agregando los datos de bytesRcvd. Sin embargo, nunca actualiza bytesRcvd. Necesita capturar el valor de retorno de la llamada al calcetín. Recibir en bytesRcvd. Si esto no soluciona el problema, significará que hay problemas de comunicación entre el servidor y el cliente (tenga en cuenta que está utilizando UDP para que no sea irrazonable) o que el mensaje sea más corto en longitud que esperado.


Tuve el mismo problema y encontré que mi solución era verificar el socket. Disponible antes de intentar recibir.

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)); }