/**
* 从 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);
网友评论