接口:Framer.java:
package com.tcpip;
import java.io.IOException;
import java.io.OutputStream;
/**
* tcp/ip协议中消息传输对帧消息的操作
* @author
*
*/
public interface Framer {
/**
* 将帧消息写入到输出流
* @param message 帧消息
* @param out 输出流
* @throws IOException
*/
void frameMsg(byte[] message,OutputStream out) throws IOException;
/**
* 读取下一帧消息,以字节数组返回
* @return
* @throws IOException
*/
byte[] nextMsg() throws IOException;
}
下面是两种成帧方法:
package com.tcpip;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 基于定界符的成帧方法
* @author
*
*/
public class DelimFramer implements Framer {
private InputStream in;
private static final byte DELIMITER= '\n';
public DelimFramer(InputStream in){
this.in = in;
}
/*
* 将帧消息输出到流中,同时也输出定界符
* @see com.tcpip.Framer#frameMsg(byte[], java.io.OutputStream)
*/
@Override
public void frameMsg(byte[] message, OutputStream out) throws IOException {
for(byte b:message){
if(b==DELIMITER){
throw new IOException("Message contains delimiter");
}
}
out.write(message);
out.write(DELIMITER);
out.flush();
}
/*
* 读取下一帧消息
* @see com.tcpip.Framer#nextMsg()
*/
@Override
public byte[] nextMsg() throws IOException {
ByteArrayOutputStream messageBuffer = new ByteArrayOutputStream();
int nextByte ;
while((nextByte=in.read())!=DELIMITER){
if(nextByte == -1){
if(messageBuffer.size()==0){
return null;
}else{
throw new EOFException("Non-empty message without delimiter");
}
}
messageBuffer.write(nextByte);
}
return messageBuffer.toByteArray();
}
}
package com.tcpip;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 基于长度的成帧的方法
* @author
*
*/
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;
public LengthFramer(InputStream in) throws IOException{
this.in = new DataInputStream(in);
}
/*
* 将帧消息输出到流中,在输出消息前先将消息的长度输出,放在前两个字节
* @see com.tcpip.Framer#frameMsg(byte[], java.io.OutputStream)
*/
@Override
public void frameMsg(byte[] message, OutputStream out) throws IOException {
if(message.length>MAXMESSAGELENGTH){
throw new IOException("message too long");
}
out.write((message.length>>BYTESHIFT)&BYTEMASK);
out.write(message.length&BYTEMASK);
out.write(message);
out.flush();
}
/*
* 读取下一帧消息
* @see com.tcpip.Framer#nextMsg()
*/
@Override
public byte[] nextMsg() throws IOException {
int length;
try{
//读取两个字节
length = in.readUnsignedShort();
}catch(EOFException e){
return null;
}
byte[] msg = new byte[length];
//将阻塞等待,直到接收到足够的字节填满数组
in.readFully(msg);
return msg;
}
}