大家好:
今天我想介绍一下socket中字节流的读取方式,避免在socket读取过程中发生的断包问题。
1.设计字节发送的方式
在字节流的读写过程中,需要先发送一个代表发送内容长度的字节,然后再发送内容,在接收端先接受发送端发送的内容长度,再根据长度来读取相应的内容。
2.构建字节流的读写类
BufferedInputStream in = new BufferedInputStream(socket.getInputStream()); BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
3.发送端的发送方式
out.write(NumberUtil.intToByte(data.length));// NumberUtil类是把int和字节转换的类,在附件中附送 out.write(data); out.flush();
4.接收端的接收方式
protected byte[] read() throws IOException { byte[] buf = null; // 读取长度 int contentLength = readInt(); // 如果消息的长度不够 if (contentLength > in.available()) { buf = BytesUtil.readBytes(in, contentLength);//BytesUtil类为读取指定长度字节的一个共通类,在附件中附送,也就是说当前缓冲流的可读字节长度<真实字节长度,那么我们需要一直读,直到读取了我们需要的长度 } else { buf = new byte[contentLength]; in.read(buf, 0, contentLength); } return buf; } private int readInt() throws IOException { // 四个字节大小 byte[] tmpByte = new byte[4]; // 读取四个字节判断消息长度 in.read(tmpByte, 0, 4); // 将byte转为int return NumberUtil.byteToInt(tmpByte); }
5.介绍readBytes方法
/** * 读取输入流中指定字节的长度 * * @param in 输入流 * @param length 指定长度 * @return 指定长度的字节数组 */ public static byte[] readBytes(InputStream in, long length) throws IOException { ByteArrayOutputStream bo = new ByteArrayOutputStream();// 建立字节流 byte[] buffer = new byte[1024];//1024长度 int read = 0; while (read < length) {// 循环将需要读取内容写入到bo中 int cur = in.read(buffer, 0, (int) Math.min(1024, length - read)); if (cur < 0) {//直到读到的返回标记为-1,表示读到流的结尾 break; } read += cur;//每次读取的长度累加 bo.write(buffer, 0, cur); } return bo.toByteArray();//返回内容 }