socket定长消息发送遇到的问题

背景:在学习socket定长消息的时候遇到了几个问题,这里总结一下

public class SocketServer {
  public static void main(String[] args) throws Exception {
    // 监听指定的端口
    int port = 55533;
    ServerSocket server = new ServerSocket(port);

    // server将一直等待连接的到来
    System.out.println("server将一直等待连接的到来");
    Socket socket = server.accept();
    // 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
    InputStream inputStream = socket.getInputStream();
    byte[] bytes;
    // 因为可以复用Socket且能判断长度,所以可以一个Socket用到底
    while (true) {
      // 首先读取两个字节表示的长度
      int first = inputStream.read();
      //如果读取的值为-1 说明到了流的末尾,Socket已经被关闭了,此时将不能再去读取
      if(first==-1){
        break;
      }
      int second = inputStream.read();
      int length = (first << 8) + second;
      // 然后构造一个指定长的byte数组
      bytes = new byte[length];
      // 然后读取指定长度的消息即可
      inputStream.read(bytes);
      System.out.println("get message from client: " + new String(bytes, "UTF-8"));
    }
    inputStream.close();
    socket.close();
    server.close();
  }
}
public class SocketClient {
  public static void main(String args[]) throws Exception {
    // 要连接的服务端IP地址和端口
    String host = "127.0.0.1";
    int port = 55533;
    // 与服务端建立连接
    Socket socket = new Socket(host, port);
    // 建立连接后获得输出流
    OutputStream outputStream = socket.getOutputStream();
    String message = "你好  yiwangzhibujian";
    //首先需要计算得知消息的长度
    byte[] sendBytes = message.getBytes("UTF-8");
    //然后将消息的长度优先发送出去
    outputStream.write(sendBytes.length >>8);
    outputStream.write(sendBytes.length);
    //然后将消息再次发送出去
    outputStream.write(sendBytes);
    outputStream.flush();
    //==========此处重复发送一次,实际项目中为多个命名,此处只为展示用法
    message = "第二条消息";
    sendBytes = message.getBytes("UTF-8");
    outputStream.write(sendBytes.length >>8);
    outputStream.write(sendBytes.length);
    outputStream.write(sendBytes);
    outputStream.flush();
    //==========此处重复发送一次,实际项目中为多个命名,此处只为展示用法
    message = "the third message!";
    sendBytes = message.getBytes("UTF-8");
    outputStream.write(sendBytes.length >>8);
    outputStream.write(sendBytes.length);
    outputStream.write(sendBytes);    
    
    outputStream.close();
    socket.close();
  }
}

这里的代码转自https://blog.youkuaiyun.com/roy_70/article/details/72519189

问题:

        代码中为什么要发送两次,第一次的右移八位的作用是什么

原因:

        定长发送数据,我们首先要将数据的长度发送给服务端。因为write是按字节发送的,如果为Integer类型的话,会强转成byte类型,只保留最低的这里发送八位,所以为了保证数据的完整性,我们需要将长度分成字节大小。一个Int类型等于四个字节,至于为什么发送两个字节,作者说:“一般呢,如果用作命名发送,两个字节就够了,如果还不放心4个字节基本就能满足你的所有要求”。

        那么发送的两次有什么不同呢,第一次的将int的第8到16位挪到了第0到8位上,然后转byte类型的时候就可以将8到16位的值发送过去。其实本质上就是将int类型拆分成四个字节发送,然后服务端在将四个字节拼接成int类型。

问题:

        流的read()方法返回的int类型的值有什么用

回答:

       返回值是用来标识流结尾的,当返回值为-1时,说明socket已经被关闭,不能再去读取了

       无参数的read方法,读取的数据其实也就时int类型的返回值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值