2012-03-29 16 views
4

Ich habe WPF C# -Anwendung, die mit einer SPS (d. H. Schreiben/lesen Omron SPS Speicheradressen) über Ethernet (UDP-Pakete) mit FINS Befehl/Frame.Hängt an Socket.Receive ohne Ausnahme

Ich kann erfolgreich Befehl WRITE SPS-Adresse senden, aber die Anwendung hängt/stürzt ab, wenn während eines antwortet von der SPS ein LESEN Befehl zu bekommen versuchen.

FINS Paketrahmen von PC zu SPS gesendet werden:

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

folgende Code ist mein Sockel senden und empfangen:

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

Ich habe auch versucht Try zu verwenden Catch, aber keine Ausnahme wird während der Anwendung gefangen hängt. Ich habe eventvwr, die sagt:

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

enter image description here

Antwort

4

Der Grund, warum bist du Anwendung hängt, ist offensichtlich, da Ihre Anwendung für immer wartet auf Daten von der Quelle abrufen. Es ist eine gute Übung, lange laufende IO auf einem Hintergrund-Thread zu planen oder die asynchronen Versionen von Senden und Empfangen zu verwenden. Der Code enthält einen Fehler in den folgenden Zeilen:

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

    totalBytesRcvd += bytesRcvd; 
} 

Sie warten auf totalBytesRcvd die Höhe der erwarteten Bytes enthalten, und Sie aktualisieren es durch die bytesRcvd Daten hinzufügen. Sie aktualisieren nie BytesRcvd. Sie müssen den Rückgabewert des Aufrufs an sock.Receive in bytesRcvd abfangen. Wenn dies das Problem nicht behebt, bedeutet dies, dass es Kommunikationsprobleme zwischen dem Server und dem Client gibt (beachten Sie, dass Sie UDP verwenden, so dass dies nicht unvernünftig ist) oder dass die tatsächliche Nachricht kürzer ist als erwartet.

+0

Ich habe Code (und Frage) bearbeitet, wie Sie vorgeschlagen haben, einige Probleme bestehen fort. Um zu verdeutlichen: Der Absturz ist nicht auf endlose while-Schleifen zurückzuführen, sondern hängt an der Receive-Methode. Ich hatte das mit einer einfachen MessageBox in der Schleife bestätigt. – KMC

+2

@KMC - Wenn die tatsächliche Antwortlänge kürzer als 256 Bytes ist, wird Ihre Anwendung hängen, da ein Aufruf zu empfangen nie zurückgegeben wird (bis Timeout trifft). Außerdem, da Sie UDP verwenden, gibt es keine Garantie, dass die eingehende Nachricht korrekt ist. Vielleicht sind einige Bytes durcheinander, einige Bytes sind hinzugefügt oder einige Bytes fehlen (in diesem Fall wird Ihre Anwendung auch hängen, da die erwartete Nachrichtenlänge niemals empfangen wird). Sie müssen diese Attribute berücksichtigen – Polity

+0

Sie sind richtig! Die Länge war eines der Probleme, die dazu führten, dass der Code hängen blieb und verschiedene andere Probleme, die ich im FINS-Paket behoben hatte. Ich werde später meine Lösung veröffentlichen. – KMC

0

Ich hatte das gleiche Problem, und meine Lösung war zu überprüfen Socket.Available vor dem Versuch zu erhalten.

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