socket通讯时出现大包

xiaobeiweng 2017-05-21 05:36:20
正常情况下包的长度是9~500左右的长度的,后台基本不会发来大包,后台发送日志也是正常的,但是android 端就经常出现这个情况,要怎么处理,看了网上的文章,说是粘包,也提到一些思路,我这边是用自定义协议的,结合我的项目用代码实现思路也不清晰,希望大神路过指点一二。

下面是错误信息
java.lang.OutOfMemoryError: Failed to allocate a 842019138 byte allocation with 16777216 free bytes and 481MB until OOM
at fuhao.com.app.net.TcpSocketZ$ReceiveThread.run(TcpSocketZ.java:255)


下面是代码:代码有点乱,还没做整理,这个是TcpSocket实现Runnable的run方法:
 @Override
        public synchronized void run() {
            try {
                int packetLen = 0;
                while (isRunning) {
                    if (!isConnected) {
                        mSocket = new Socket(HostIP, Port);
                        mSocket.setSendBufferSize(1024);
                        mSocket.setReceiveBufferSize(1024);
                        mSocket.setTcpNoDelay(true);
                        mSocket.setKeepAlive(true);
                        mDos = new DataOutputStream(mSocket.getOutputStream());
                        mDis = new DataInputStream(mSocket.getInputStream());
                        handshark();
                        isConnected = true;
                        startHeartBeat();
                    } else {
                        if (mDis.available() >= 4) {
                            packetLen = mDis.readInt();
                            L.e("TcpSocketZ", "-----packetLen------" + packetLen);
                            if (packetLen > 0) {
                                byte iszlib = mDis.readByte();
                                if (iszlib == (byte) 1) {
                                    try {
                                        byte[] inputData = new byte[packetLen - 1];
                                        utils.readData(mDis, inputData, 0, packetLen - 1);
                                        byte[] result = CompressUtil.decompress(inputData);
                                        byteReader br = new byteReader(result);
                                        int alias = br.readInt();
                                        L.e("TcpSocketZ", "recv packet zlib ------" + String.valueOf(alias));
                                        baseProto obj = ClassFactory.getProtoObject(alias);
                                        if (obj != null) {
                                            obj.parseFrom(br);
                                            EventBus.getDefault().post(new ResEvent(obj));
                                        }
                                    } catch (DataFormatException e) {
                                        e.printStackTrace();
                                    }
                                } else {
                                    byte[] inputData = new byte[packetLen - 1];
                                    utils.readData(mDis, inputData, 0, packetLen - 1);
                                    byteReader br = new byteReader(inputData);
                                    int alias = br.readInt();
                                    L.e("TcpSocketZ", "packet alias------" + String.valueOf(alias));
                                    if (alias == 20002) {
                                        backTime = 0;
                                    }
                                    baseProto obj = ClassFactory.getProtoObject(alias);
                                    if (obj != null) {
                                        obj.parseFrom(br);
                                        EventBus.getDefault().post(new ResEvent(obj));
                                    }
                                }
                            }
                        }
                    }
                }
                mDos.close();
                mDis.close();
                if (mSocket != null) {
                    mSocket.close();
                    mSocket = null;
                }
                this.isRunning = false;
                reconnect();
            } catch (EOFException e) {
                this.isConnected = false;
                try {
                    mDos.close();
                    mDis.close();
                    if (mSocket != null) {
                        mSocket.close();
                        mSocket = null;
                    }
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                reconnect();
                e.printStackTrace();
            } catch (SocketException e) {
                e.printStackTrace();
                this.isConnected = false;
                try {
                    mDos.close();
                    mDis.close();
                    if (mSocket != null) {
                        mSocket.close();
                        mSocket = null;
                    }
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                reconnect();
                e.printStackTrace();
            } catch (UnknownHostException e) {
                e.printStackTrace();
                this.isConnected = false;
                try {
                    mDos.close();
                    mDis.close();
                    if (mSocket != null) {
                        mSocket.close();
                        mSocket = null;
                    }
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                reconnect();
                e.printStackTrace();
            } catch (IOException e) {
                this.isConnected = false;
                try {
                    mDos.close();
                    mDis.close();
                    if (mSocket != null) {
                        mSocket.close();
                        mSocket = null;
                    }
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                reconnect();
                e.printStackTrace();
 
            }
        }


错误的是出现在上面代码的第40行
...全文
557 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
zs12900 2017-06-05
  • 打赏
  • 举报
回复
我也遇到了一个问题,就是通过NIO接收,客户端循环发送太快会导致接收字节不对,如果间隔100Ms或者1s就没问题
逗泥丸的平方 2017-06-05
  • 打赏
  • 举报
回复
OOM 啊 是一个socket多次发送请求的情况吗? 粘包先看看编码吧 再就是分隔符是什么.. 代码有点懒得看.. 既然是自定义协议还是要讲讲协议吧
santan 2017-06-04
  • 打赏
  • 举报
回复
packetLen = mDis.readInt();,这是包剩余的字节数吧,这个肯定算错了。 ,
什么都不能 2017-06-04
  • 打赏
  • 举报
回复
服务器向客户端发了800M的内容?是什么文件?
bcsflilong 2017-06-02
  • 打赏
  • 举报
回复
第一一个byte 长度1024 之后用类似于
byte[] buf=new byte[1024];
while((by=bis.read(buf))!=-1)
{
bos.write(buf,0,by);
}
xiaobeiweng 2017-06-01
  • 打赏
  • 举报
回复
引用 2 楼 bcsflilong 的回复:
循环读写 别一次都写进来 不就可以了吗
詳細要怎麼實現
_贺兰 2017-06-01
  • 打赏
  • 举报
回复
byte[] inputData = new byte[packetLen - 1]; 这句话有问题,如果长度太大,肯定OOM 如果包大小超过最大内存限制,就必须每次读取一小段(比如1K),然后将数据写到文件系统,全部收取完毕后,在分段分析包 至于粘包,很多人容易混淆了,tcp本身就不存在包的概念(记住:tcp是协议),何来粘包之说?原则上tcp可以每次只发给你一个字节,因此不能依赖tcp每次接收的字节,而是自己要在应用协议部分做好识别(普遍做法是在应用数据包前端增加长度用于分包)
xiaobeiweng 2017-05-23
  • 打赏
  • 举报
回复
是我的问题提得不够清晰?都没有回答
bcsflilong 2017-05-23
  • 打赏
  • 举报
回复
循环读写 别一次都写进来 不就可以了吗

62,624

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧