4

FINS コマンド/フレームを使用してイーサネット (UDP パケット) 経由で PLC と通信する (つまり、オムロン PLC のメモリ アドレスの書き込み/読み取り) WPF C# アプリケーションがあります。

コマンドをWRITE PLC アドレスに正常に送信できますが、 READコマンド中に 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
};

次のコードは、ソケットの送受信です。

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

Try-Catchも使用しようとしましたが、アプリケーションのハング中に例外はキャッチされません。私は言うeventvwrをチェックしました:

ソース: Application Hangs - "...stopped interacting with Windows and was closed" 詳細:(screenshot below)

ここに画像の説明を入力

4

2 に答える 2

4

アプリケーションがハングする理由は、アプリケーションがソースからデータを取得するのを永遠に待っているためです。バックグラウンド スレッドで実行時間の長い IO をスケジュールするか、非同期バージョンの送受信を使用することをお勧めします。あなたのコードには、次の行にバグが含まれています:

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

    totalBytesRcvd += bytesRcvd; 
} 

totalBytesRcvd に予想されるバイト数が含まれるのを待っており、bytesRcvd データを追加して更新しています。それでも、bytesRcvd を更新することはありません。sock.Receive への呼び出しの戻り値を bytesRcvd でキャッチする必要があります。これで問題が解決しない場合は、サーバーとクライアントの間の通信に問題があることを意味します (UDP を使用しているため、不合理ではないことに注意してください)。または、実際のメッセージの長さが期待される。

于 2012-03-29T03:46:04.890 に答える