2012-03-29 14 views
4

FINSコマンド/フレームを使用してEthernet(UDPパケット)を介してPLCと通信するWPF C#アプリケーションがあります。ソケットでハングアップする例外なしで受信する

READコマンドの実行中にPLCからの応答を取得しようとしたとき、私は成功しWRITE PLCアドレスにコマンドを送信しますが、アプリケーションハング/クラッシュすることができます。

FINSパケットフレームPLCにPCから送信する:次のコード

// 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-を使用することも試してみましたキャッチ、アプリケーションのハング中に例外がキャッチされません。アプリケーションがに永遠に待っているので、あなたはアプリケーションがハングしている理由は明らかである(screenshot below)

enter image description here

答えて

4

源泉:Application Hangs - "...stopped interacting with Windows and was closed" 詳細私はeventvwrと、と言うチェックソースからデータを取得する。バックグラウンドスレッドで長時間実行される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を使用しているので、不合理でない可能性があります)。または、実際のメッセージの長さが期待される。

+0

あなたが提案したコードを編集しましたが、問題が残っています。明確にするために:クラッシュは無限ループのためではなく、Receiveメソッドでハングします。私は、ループ内の単純なMessageBoxでそれを確認しました。 – KMC

+2

@KMC - 私が言ったように、実際の応答の長さが256バイトよりも短い場合、receiveへの呼び出しは決して戻りません(タイムアウトヒットまで)。それ以外にも、UDPを使用しているので、受信メッセージが正しいという保証はありません。おそらく、いくつかのバイトが混乱しているか、いくつかのバイトが追加されているか、または何らかのバイトが欠落していることがあります(この場合、予想されるメッセージの長さは決して受信されないため、アプリケーションもハングします)。あなたはこれらの属性を考慮に入れる必要がありますあなたは正しいです – Polity

+0

!コードの長さが問題の原因となり、FINSパケットに固定されたさまざまな問題が発生しました。私は後で私の解決策を掲載します。 – KMC

0

私は同じ問題を抱えていました。私の解決策は、受信を試みる前にsocket.Availableをチェックすることでした。

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)); 
} 
関連する問題