Java网络编程中的字节流传输时输出为负数输出读取却为正数

在使用socket编程时,发现服务端通过字节输出流输出一个负数,而客户端读入的却是一个正数。比如-1变成了255,-128变成了128,-126变成了130, 如图所示:
服务端:服务端输出-1
客户端:
客户端读入为255

要了解原因首先需要理解原码、补码和反码的区别:

  • 原码:二进制码,原码就是最高位为符号位(1代表负数,0代表正数),而剩下的低位组成真值,比如4的原码为00000100,-4的原码为10000100,两者之间只有最高位不同。
  • 反码:正数的反码为其本身,负数的反码为除符号位之外其余位全部取反,比如-4的反码为11111011。
  • 补码:正数的补码等于其本身,负数的补码是反码加1,-4的补码为11111100。
  • 计算机以补码形式存储数字,补码的出现方便了计算机底层实现加减计算。
  • 同时-128的8位补码为10000000,为什么这么表示可以百度一下。

在Java中一个byte为8位,一个int为32位,因此当我们将byte转化为int时,会保持其值不变来进行转化,而不是简单的将其放在int的低八位中。同时由于byte的取值范围为-128到127,因此byte和int的补码在-128到127的范围内的低八位的补码表示都一样,比如byte形式的-128补码为10000000,int形式的补码为10000000000000000000000010000000

socket中当我们使用字节流来传输时,比如write方法,可以看到Java中的实现如下:

通过将byte转化为int来传输

public abstract void write(int b) throws IOException;

由于write使用字节传输,int中有用的信息只有低八位(一个字节),在服务端到客户端的传输过程中从int截取低八位进行传输,客户端接受到时会将该字节与值为255的int型变量(0x000000FF)进行&操作来转化为int变量,这就是read()方法读取到的值,这也就是为什么通过read读取字节时因此读到的值总是为正数的原因。

public abstract int read() throws IOException;

测试代码:

服务端:

@Test
    public void testByteAndInt() throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        Socket socket = serverSocket.accept();
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        out.write(-1);
    }

客户端:

public void TestClient() throws IOException {
        Socket socket = new Socket("127.0.0.1", 8080);
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        System.out.println(in.read());
        // 在服务端write时写的是-128 100000...10000000(原码) 补码为11111...01111111
        // 那么在传输到客户端的时候也应该是-128啊,但是为什么输出为128
        // -126时输出为130
        // -1时输出为255
    }
        

比如-1的补码为0xFF,在write()传输时转化为0xFFFFFFFF,在read读到的int值为0x000000FF,值为255。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值