tcp / ip message transmission operation protocol message frame

Interface: 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;

}


Here are two framing methods:

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;
	}

}



Reproduced in: https: //my.oschina.net/u/2552902/blog/543834

Guess you like

Origin blog.csdn.net/weixin_33860528/article/details/92326847