Java的TCP/IP编程学习--基于长度的成帧

基于长度的成帧

package framer;

import java.io.*;

/**
 * @ClassName LengthFramer
 * @Description TODO
 * LengthFramer.java类实现了基于长度的成帧方法,适用于长度小于65535(216-1)
 * 字节的消息。发送者首先给出指定消息的长度,并将长度信息以b1g-endian顺序存入两
 * 个字节的整数中,再将这两个字节放在完整的消息内容前,连同消息一起写入输出流。
 * 在接收端,我们使用DatalnputStream以读取整型的长度信息;readFully()方法将阻塞
 * 等待,直到给定的数组完全填满,这正是我们需要的。值得注意的是,使用这种成帧方
 * 法,发送者不需要检查要成帧的消息内容,而只需要检查消息的长度是否超出了限制。
 * @Author Cays
 * @Date 2019/3/17 8:45
 * @Version 1.0
 **/
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;

    /**
     * 获取赖消息源的输入流,并将其包裹在一个DataInputStream
     * @param in
     * @throws IOException
     */
    public LengthFramer(InputStream in) throws IOException{
        this.in = new DataInputStream(in);
    }

    @Override
    public void frameMsg(byte[] message, OutputStream out) throws IOException {
        if (message.length>MAXMESSAGELENGTH){
            throw new IOException("message too long");
        }
        /**
         * 由于我们用的是长为两个字节的字段,因此消息的长度不能超过65535。
         * (注意该值太大而不能存入一个short型整数中,
         * 因此我们每次只向输出流写一个字节)
         */
        out.write((message.length>>BYTESHIFT)&BYTEMASK);
        out.write(message.length&BYTEMASK);
        out.write(message);
        out.flush();
    }

    @Override
    public byte[] nextMsg() throws IOException {
        int length;
        try {
            //readUnsignedShort()方法读取两个字节,
            // 将它们作为big-endian整数进行解释,并
            //以int型整数返回它们的值。
            length = in.readUnsignedShort();
        }catch (EOFException e){
            return null;
        }
        byte[] msg=new byte[length];
        //阻塞等待,直到接收到足够的字节来填满指定的字节数组
        in.readFully(msg);
        return msg;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39400984/article/details/88697921