27

実際のサーバーポート値を取得できるように、2バイトをunsignedshortに変換しようとしています。私は、応答フォーマットの下でこのプロトコル仕様に基づいています。これにBitConverter.ToUint16()を使用してみましたが、問題は、期待値をスローしていないように見えることです。実装例については、以下を参照してください。

int bytesRead = 0;

while (bytesRead < ms.Length)
{
    int first = ms.ReadByte() & 0xFF;
    int second = ms.ReadByte() & 0xFF;
    int third = ms.ReadByte() & 0xFF;
    int fourth = ms.ReadByte() & 0xFF;
    int port1 = ms.ReadByte();
    int port2 = ms.ReadByte();
    int actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port1 , (byte)port2 }, 0);
    string ip = String.Format("{0}.{1}.{2}.{3}:{4}-{5} = {6}", first, second, third, fourth, port1, port2, actualPort);
    Debug.WriteLine(ip);
    bytesRead += 6;
}

1つのサンプルデータが与えられたとしましょう。たとえば、2バイトの値に対して105と135があり、変換後の期待されるポート値は27015ですが、代わりにBitConverterを使用して34665の値を取得します。

私はそれを間違った方法でやっていますか?

4

3 に答える 3

32

BitConverter呼び出しの値を逆にすると、期待どおりの結果が得られるはずです。

int actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port2 , (byte)port1 }, 0);

リトルエンディアンアーキテクチャでは、下位バイトは配列の2番目である必要があります。また、lasseespeholtがコメントで指摘しているように、ビッグエンディアンアーキテクチャでは順序を逆にする必要があります。これは、 BitConverter.IsLittleEndianプロパティで確認できます。または、 IPAddress.HostToNetworkOrderを使用する方が全体的に優れたソリューションになる場合があります(最初に値を変換してから、そのメソッドを呼び出して、エンディアンに関係なくバイトを正しい順序に配置します)。

于 2011-04-21T21:14:59.963 に答える
13

BitConverterは正しいことを行っています。下位バイトと上位バイトが混同されているだけです。ビットシフトを使用して、手動で確認できます。

byte port1 = 105;
byte port2 = 135;

ushort value = BitConverter.ToUInt16(new byte[2] { (byte)port1, (byte)port2 }, 0);
ushort value2 = (ushort)(port1 + (port2 << 8)); //same output
于 2011-04-21T21:16:34.647 に答える
10

リトルエンディアンアーキテクチャとビッグエンディアンアーキテクチャの両方で作業するには、次のようなことを行う必要があります。

if (BitConverter.IsLittleEndian)
    actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port2 , (byte)port1 }, 0);
else
    actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port1 , (byte)port2 }, 0);
于 2011-04-21T21:21:57.297 に答える