数据包的结构定义如下:
消息头12字节,分别代表3个整形值:数据包的总长度、命令类型、序列号
消息体长度不固定,有数据包的总长度标明使用Buffer的程序代码如下:
public CmppPack receive() throws IOException {
CmppPack pack = null; if (sock != null)
try {
byte[] bHead = new byte[12];//定义消息头的长度
DataInputStream in = new DataInputStream(sock.getInputStream());
BufferedInputStream bis = new BufferedInputStream(in,1024); bis.read(bHead);//读取消息头
int len = GFCommon.bytes2int(GFCommon.bytesCopy(bHead,0,4));//把4字节转成整形
if (len > 0 && len < MAX_LEN) {
int cmd = GFCommon.bytes2int(GFCommon.bytesCopy(bHead,4,4));
int seq = GFCommon.bytes2int(GFCommon.bytesCopy(bHead,8,4)); int bodyLen = len - 12;
byte[] msg = new byte[bodyLen];
bis.read(msg);//读取消息体 CmppHead head = new CmppHead(len, cmd, seq);
CmppBody body = new CmppBody(msg);
pack = new CmppPack(head, body); 
}   
} catch (SocketTimeoutException e) {
// logger.warn("time out");
} catch (IOException e) {
throw e; 
} return pack;
}发现在测试过程中连续发送100个数据包就会有丢失,单个单个的发就正常,如果读取时不使用Buffer,直接从IO流中读取数据,连续发包一切正常,代码如下:
public CmppPack receiveNoBuffer() throws IOException {
CmppPack pack = null; if (sock != null)
try {
DataInputStream in = new DataInputStream(sock.getInputStream());
int len = in.readInt();
if (len > 0 && len < MAX_LEN) {
int cmd = in.readInt();
int seq = in.readInt();
int bodyLen = len - 12;
byte[] msg = new byte[bodyLen];
in.read(msg); CmppHead head = new CmppHead(len, cmd, seq);
CmppBody body = new CmppBody(msg);
pack = new CmppPack(head, body); } } catch (SocketTimeoutException e) {
// logger.warn("time out");
} catch (IOException e) {
throw e; } return pack;
}

解决方案 »

  1.   

    代码有点乱,重新整理一下:
    public CmppPack receive() throws IOException {
           CmppPack pack = null;       if (sock != null)
    try {
    byte[] bHead = new byte[12];//定义消息头的长度
    DataInputStream in = new DataInputStream(sock.getInputStream());
    BufferedInputStream bis = new BufferedInputStream(in,1024); bis.read(bHead);//读取消息头
    int len = GFCommon.bytes2int(GFCommon.bytesCopy(bHead,0,4));//把4字节转成整形
    if (len > 0 && len < MAX_LEN) {
    int cmd = GFCommon.bytes2int(GFCommon.bytesCopy(bHead,4,4));
    int seq = GFCommon.bytes2int(GFCommon.bytesCopy(bHead,8,4)); int bodyLen = len - 12;
    byte[] msg = new byte[bodyLen];
    bis.read(msg);//读取消息体 CmppHead head = new CmppHead(len, cmd, seq);
    CmppBody body = new CmppBody(msg);
    pack = new CmppPack(head, body); 
    }   
    } catch (SocketTimeoutException e) {
    // logger.warn("time out");
    } catch (IOException e) {
    throw e; 
             } return pack;
    }
      

  2.   

    public CmppPack receiveNoBuffer() throws IOException {
          CmppPack pack = null;      if (sock != null)
    try {
    DataInputStream in = new DataInputStream(sock.getInputStream());
    int len = in.readInt();
    if (len > 0 && len < MAX_LEN) {
    int cmd = in.readInt();
    int seq = in.readInt();
    int bodyLen = len - 12;
    byte[] msg = new byte[bodyLen];
    in.read(msg); CmppHead head = new CmppHead(len, cmd, seq);
    CmppBody body = new CmppBody(msg);
    pack = new CmppPack(head, body); } } catch (SocketTimeoutException e) {
    // logger.warn("time out");
    } catch (IOException e) {
    throw e; } return pack;
    }
      

  3.   

    CMPP 的包?
    BufferedInputStream之前想是用一个大的byte[]缓存点数据。
    但现在由于你的包的格式长度比较确定消息头12字节
    前四个字节是总长
    之后是命令字,序列号。
    保险点直接从socket的inputStream拿,自己转换为数字之类的,高字节在前,低字节在后。做网关的兄弟都来瞄瞄嘛。SP不好混了吧?
      

  4.   

    是CMPP包,因为用Buffer包装一下速度会比较快,直接从输入流读取的话是没问题.
    使用Buffer包装后一个包一个包的发没有问题,便大量发包就会有丢失的现象
      

  5.   

    直接拿几乎是每读取一个字节(除了消息头之外)都要访问一次IO,开销肯定会比较大。用Bufer包装显然直接访问IO的次数会大大降低