ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java 粘包和半包问题

2022-09-16 16:04:04  阅读:275  来源: 互联网

标签:Java splitbyte read rlen 粘包 new close 半包 buf


/**
 * 从 buf 中查找 "\r\n",并返回这段(包括 \r\n)空间的长度。
 * 如果 buf 中没有,则返回 0 。
 */
private static int findLineEnd(final byte[] buf, int rlen) {
    int splitbyte = 0;
    while (splitbyte + 1 < rlen) {
        if (buf[splitbyte] == '\r' && buf[splitbyte + 1] == '\n' && splitbyte + 1 < rlen) {
            return splitbyte + 2;
        }
        splitbyte++;
    }
    return 0;
}

/**
 * 半包、粘包问题解决:
 *      从 InputStream 中找一行数据并返回。「一行」的标志是截止到 \r\n,不包括 \r\n 。
 */
private static String readLine(InputStream inputStream) throws IOException, RuntimeException {
    int splitbyte = 0;
    int rlen = 0;
    byte[] buf = new byte[BUFSIZE];
    int read = -1;
    inputStream.mark(BUFSIZE);
    try {
        read = inputStream.read(buf, 0, BUFSIZE);
    } catch (Exception e) {
        throw new SocketException("Could not Read");
    }

    if (read == -1) {
        throw new SocketException("Could not Read");
    }

    /* buf 中存储的数据区间为: buf[0] ... buf[read-1],共 read 个字节。 */

    while (read > 0) {
        rlen += read;
        splitbyte = findLineEnd(buf, rlen);
        if (splitbyte > 0) {
            break;
        }

        read = inputStream.read(buf, rlen, BUFSIZE - rlen);
    }

    /* buf 中存储的数据区间为: buf[0] ... buf[splitbyte-1],共 splitbyte 个字节。其中包含 \r\n 在内。*/

    // -2 的目的是返回的结果内容中不包含 \r\n 。
    return new String(buf, 0, splitbyte - 2);
}

private static void safeClose(Closeable closeable) {
    try {
        if (closeable != null) {
            closeable.close();
        }
    } catch (IOException e) {
        System.out.println("Could not close: " + e.getMessage());
    }
}

private static void safeClose(Socket socket) {
    try {
        if (socket != null && !socket.isClosed()) {
            socket.close();
        }
    } catch (IOException e) {
        throw new IllegalArgumentException("Cloud not close socket: " + e.getMessage());
    }
}

private static void safeClose(ServerSocket serverSocket) {
    try {
        if (serverSocket != null && !serverSocket.isClosed()) {
            serverSocket.close();
        }
    } catch (IOException e) {
        throw new IllegalArgumentException("Cloud not close socket: " + e.getMessage());
    }
}

测试:

 String message = "hello world\r\ngoodbye";
 byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
 //System.out.println(findLineEnd(bytes, bytes.length));

InputStream stream = new ByteArrayInputStream(bytes);

String line = readLine(stream);

System.out.println(line);

标签:Java,splitbyte,read,rlen,粘包,new,close,半包,buf
来源: https://www.cnblogs.com/hemiao3000/p/16700193.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有