TcpSocketメッセージの終了境界を検索する方法
7305 ワード
フレーム化方法
import java.io.IOException;
import java.io.OutputStream;
public interface Framer {
void frameMsg(byte[] message, OutputStream out) throws IOException;
byte[] nextMsg() throws IOException;
}
デリミタベース(Delimiter-based)
import java.io.*;
public class DelimFramer implements Framer {
private InputStream in; // data source
private static final byte DELIMITER = '
'; // message delimiter
public DelimFramer(InputStream in) {
this.in = in;
}
public void frameMsg(byte[] message, OutputStream out) throws IOException {
// ensure that the message does not contain the delimiter
for (byte b : message) {
if (b == DELIMITER) {
throw new IOException("Message contains delimiter");
}
}
out.write(message);
out.write(DELIMITER);
out.flush();
}
public byte[] nextMsg() throws IOException {
ByteArrayOutputStream messageBuffer = new ByteArrayOutputStream();
int nextByte;
// fetch bytes until find delimiter
while ((nextByte = in.read()) != DELIMITER) {
if (nextByte == -1) { // end of stream?
if (messageBuffer.size() == 0) { // if no byte read
return null;
} else { // if bytes followed by end of stream: framing error
throw new EOFException("Non-empty message without delimiter");
}
}
messageBuffer.write(nextByte); // write byte to buffer
}
return messageBuffer.toByteArray();
}
}
長さベース(Explicit length)
import java.io.*;
public class LengthFramer implements Framer {
public static final int MAXMESSAGELENGTH = 65535;
public static final int BYTEMASK = 0xff;
public static final int SHORTMASK = 0xffff;
public static final int BYTESHIFT = 8;
private DataInputStream in; // wrapper for data I/O
public LengthFramer(InputStream in) throws IOException {
this.in = new DataInputStream(in);
}
public void frameMsg(byte[] message, OutputStream out) throws IOException {
if (message.length > MAXMESSAGELENGTH) {
throw new IOException("message too long");
}
// write length prefix
out.write((message.length >> BYTESHIFT) & BYTEMASK);
out.write(message.length & BYTEMASK);
// write message
out.write(message);
out.flush();
}
public byte[] nextMsg() throws IOException {
int length;
try {
length = in.readUnsignedShort(); // read 2 bytes
} catch (EOFException e) { // ,
return null;
}
// 0 <= length <= 65535
byte[] msg = new byte[length];
in.readFully(msg); // if exception, it's a framing error.
return msg;
}
}