簡體   English   中英

字節數組中的封裝包

[英]Encapsulation packet in byte array

我正在為需要使用CIP協議通過TCP / IP進行通信的應用程序構建一個C#庫。 (這是PLC使用的工業協議)。 我的庫基於一個開源的VB.net項目。

在此輸入圖像描述

我在Microsoft開發人員網絡上找到了很多信息來設置套接字。 下一步是注冊會話,所以我需要使用Socket.Receive方法接收信息。 同樣,關於開發者網絡的許多有用信息。

我正在構建這樣的標題:

private string Build_Header(byte[] Command, int Length) //Build the encapsulate message header. The header is 24 bytes fixed length and includes the command and the length of the optional data portion
    {
        string Header;
        byte[] HeaderStatus = { 0x0, 0x0, 0x0, 0x0 };
        byte[] HeaderOption = { 0x0, 0x0, 0x0, 0x0 };

        try
        {
            Header = Encoding.Unicode.GetString(Command);
            Header += Encoding.Unicode.GetString(BitConverter.GetBytes(Length));
            Header += Encoding.Unicode.GetString(BitConverter.GetBytes(SessionID));
            Header += Encoding.Unicode.GetString(HeaderStatus);
            Header += Encoding.Unicode.GetString(BitConverter.GetBytes(Context));
            Header += Encoding.Unicode.GetString(HeaderOption);

            return Header;
        }
        catch (Exception ex)
        {
            Debug.WriteLine("Failed to create header: {0}", ex);
            return "FAILED";
        }
    }

Witch是VB函數的副本:

Private Function _build_header(Command As Byte(), length As Short)
    'Build the encapsulate message header
    'The header is 24 bytes fixed length, and includes the command and the length of the optional data portion.
    Dim header As String
    Try
        header = Encoding.Unicode.GetString(Command)                             '# Command UINT
        header += Encoding.Unicode.GetString(BitConverter.GetBytes(length))      '# Length UINT
        header += Encoding.Unicode.GetString(BitConverter.GetBytes(_session))    '# Session Handle UDINT
        header += Encoding.Unicode.GetString({&H0, &H0, &H0, &H0})               '# Status UDINT
        header += Encoding.Unicode.GetString(BitConverter.GetBytes(_Context))    '# Sender Context 8 bytes
        header += Encoding.Unicode.GetString({&H0, &H0, &H0, &H0})               '# Option UDINT
        'If Not DisableLogFile Then Console.WriteLine("Header created: " + Bytes_To_String(Encoding.Unicode.GetBytes(header)) + "  , length: " _
        '                    + header.Length.ToString + "   (must be equal to 24 bytes)")
        Return header
    Catch ex As Exception
        Console.WriteLine("Failed to create header: " + ex.Message)
        Return ""
    End Try
End Function

但我收到一條錯誤消息,狀態為“Unsupported encapsulation protocol revision”。 所以我開始逐行調試,發現以下差異:

原創(VB):

VB

復制(C#):

在此輸入圖像描述

我不確定這是否是主要問題,但我至少應該采用相同的格式?

錢幣; 從哪兒開始。 K:我會坦率地說 - 你要復制的VB參考資料是垃圾 這是100%的錯誤,任何現在正在運作的東西都完全是偶然的。 對於初學者來說,這些數據不是文本 - 它是一個二進制框架。 因此,你不能返回string 返回一個byte[]是合理的。 因此,最重要的問題可能不是“我應該如何得到這個字符串”,而是“一旦我有這個字符串,我怎么把它寫到套接字”? 您的問題中沒有顯示該代碼,但我很高興地打賭, 如何將字符串寫入套接字是兩個版本之間的關鍵區別。

但是:你不應該首先處理字符串 假設該方法返回了一個byte[] 然后我們有:

byte[] header = BuildHeader(command, length);

現在只有一種方法可以將byte[]寫入流中(除非我們非常想象):

socket.Send(header, 0, header.Length);

(或涉及Stream一些類似變體)

現在; BuildHeader 應該做的是:

byte[] header = new byte[24];
// .. fill in
return header;

至於那些部分應該是什么:它取決於字節順序 ; 它看起來像UINT是2個字節,並且UDINT是4。所以,得到寫入的示例length (第二個字段,2個字節,偏移2個字節),這將是以下之一

header[2] = (byte)length;
header[3] = (byte)(length >> 8);

要么

header[2] = (byte)(length >> 8);
header[3] = (byte)length;

不幸的是, BitConverter.GetBytes無法幫助您打包緩沖區,因為它:它不允許您傳遞緩沖區和偏移量,而b:字節序由CPU定義(我們需要它是特定的字節序)。 如果VB代碼工作,它可能是little-endian(除非你有一個Itanium),所以第一個版本(小端優先)應該是正確的。

對所有字段重復此操作,您將擁有一個有效的標題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM