0

我正在计算我的数据的 16 位校验和,我需要将其发送到必须重新计算并与提供的校验和匹配的服务器。我得到的校验和值在 int 中,但我只有 2 个字节用于发送值。所以我在调用方法时正在int转换。这工作正常,直到校验和值小于 32767 之后我得到负值。shortshortToBytes

事情是java没有无符号原语,所以我无法发送大于short允许的最大值的值。

我该如何做到这一点,将 int 转换为 short 并通过网络发送,而不用担心截断和有符号和无符号 int。

同样在双方我都有java程序运行。

   private byte[] shortToBytes(short sh) {
        byte[] baValue = new byte[2];
        ByteBuffer buf = ByteBuffer.wrap(baValue);
        return buf.putShort(sh).array();
    }

    private short bytesToShort(byte[] buf, int offset) {
        byte[] baValue = new byte[2];
        System.arraycopy(buf, offset, baValue, 0, 2);
        return ByteBuffer.wrap(baValue).getShort();
    }
4

4 回答 4

1

int首先,Javashortbyte类型都是有符号的而不是无符号的。其次,当您将 Javaint转换为 ashort等时,您将获得静默截断。

这是否重要取决于校验和算法的性质。如果它是一个简单的求和或按位算法,那么当使用 Java 有符号整数实现时,该算法很有可能就很好。例如,那些“负”的 16 位校验和在被期望无符号值的东西解释时可能是正确的。

另一方面,乘法和除法的语义使得有符号和无符号的风格必须分开处理。(至少,这就是我从查看 x86 指令集的不科学方法中推断出来的......它有单独的有符号和无符号乘法和除法指令。)

编辑我知道您正在计算 CRC-16。由于这可以通过移位和异或来计算,因此在计算过程中不应该担心有符号数和无符号数。

简而言之,您无需担心。

于 2010-03-21T02:37:32.307 回答
1

char是无符号的 16 位类型。事实上,它是 Java 中唯一的无符号类型。您可以使用它来计算校验和,然后使用 aByteBuffer来获取字节,或者简单地使用按位和右移来获取字节。

请记住,bytes 已签名。

于 2010-03-21T02:40:28.737 回答
1

您仍然获得与服务器相同的位值。因此,要查看正确的数值,请将 替换ByteBuffer.wrap(baValue).getShort()ByteBuffer.wrap(baValue).getInt()。这应该为您提供与服务器相同的数值。

于 2010-03-21T02:43:15.720 回答
0

当您说您得到负值时,我假设您的意思是当您读取 16 位值并将其转换为整数时。这样做的原因是符号扩展导致最高有效位(即 1)在short扩大到时被复制int。简单的解决方法是按位和重构的整数0xFFFF,这将确保只有最不重要的 16 位是非零的。

于 2010-03-21T03:23:26.583 回答