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