java网络编程,分包接收数据的疑惑,望大侠指点!

ztenv
领域专家: 编程技术技术领域
2012-12-19 10:54:35
最近在做java接收二进制流的测试,一个服务端一个客户,服务端接收到客户端的请求后,向客户端一次性发送50kB左右的二进制数据包;包头占四个字节,指示了数据包的长度;

客户端收到四个字节的包头后,打印包体的长度length,正确,

于是分配50kb的buff,byte[] buff=new byte[length];

int canread=socket.avaliable();
//canread的大小也是正常的;

int readlen=socket.getinputstream().read(buff,0,length);
//readlen的长度为length的大小,按API的说法是读到了length个字节,但缓冲区中却没有那么多数据;
//如果readlen不可靠,那么如何才能获得可靠的接收到的数据?
//因为50kb不可能在一个TCP包中传过来,肯定分成多包来传的,我想知道我具体已经接收了多少了,给我的感觉是socket.getinputstream().read()的返回值是不可靠的;

感谢大侠的指点!
...全文
568 15 打赏 收藏 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
ztenv 2013-01-10
  • 打赏
  • 举报
回复
我已经解决这个问题了,散分。
夜雨双唱2016 2012-12-30
  • 打赏
  • 举报
回复
在网络上发送对象要记得序列化!~
夜雨双唱2016 2012-12-30
  • 打赏
  • 举报
回复
引用 10 楼 lianshaohua 的回复:
刚刚调试了一下,在循环中把每次收到的一个分包转换成可显示字符打印出来,发现几次收到的数据有的是相同的;难道socket在读完缓冲区后没有清空?反复的读一同一段内容?
我也遇到过这种情况,具体原因当时也没仔细查,不过只要把服务器端程序改成每发送一次就休眠几十毫秒就没问题了。 不过休眠几十毫秒又觉得太浪费时间,最终决定把所要发送的字节数组包装成了一个对象: class sendObj { byte[] bytes; } 然后使用objectoutputstream 和 objectinputstream,以对象的方式发送和接受也就没问题了。
MiceRice 2012-12-20
  • 打赏
  • 举报
回复
引用 10 楼 lianshaohua 的回复:
刚刚调试了一下,在循环中把每次收到的一个分包转换成可显示字符打印出来,发现几次收到的数据有的是相同的;难道socket在读完缓冲区后没有清空?反复的读一同一段内容?
除非你的发送逻辑写错了。
MiceRice 2012-12-20
  • 打赏
  • 举报
回复
常见问题,循环读取就行了,参考如下: InputStream is = socket.getinputstream(); byte[] buff=new byte[length]; int pos = 0; while (pos < length) { pos += is.read(buff, pos, length-pos); }
eviljordan 2012-12-20
  • 打赏
  • 举报
回复
楼主参照下:ByteArrayInputStream 应该可以满足你的需求!
ztenv 2012-12-20
  • 打赏
  • 举报
回复
刚刚调试了一下,在循环中把每次收到的一个分包转换成可显示字符打印出来,发现几次收到的数据有的是相同的;难道socket在读完缓冲区后没有清空?反复的读一同一段内容?
ztenv 2012-12-20
  • 打赏
  • 举报
回复
引用 5 楼 dracularking 的回复:
readlen会不对吗?按理这么简单的一个功能api不太可能会出错的
的确不对。readlen和写入buffer中的数据长度不一致,也就是: 有的时候返回了readlen,但没有读到数据。
ztenv 2012-12-20
  • 打赏
  • 举报
回复
引用 4 楼 ldh911 的回复:
常见问题,循环读取就行了,参考如下: InputStream is = socket.getinputstream(); byte[] buff=new byte[length]; int pos = 0; while (pos < length) { pos += is.read(buff, pos, length-pos); }
使用循环读了,但pos返回了读的长度,但这个长度和buf中写入的数据长度不一致,
  • 打赏
  • 举报
回复
阻塞式循环读取。 最好使用非阻塞式,接收方每接收到一次正确包就发送一个小标示给服务器发请求送下一个包。
安特矮油 2012-12-20
  • 打赏
  • 举报
回复
不是一次性发送那么多数据,那就循环读取就好
dracularking 2012-12-20
  • 打赏
  • 举报
回复
readlen会不对吗?按理这么简单的一个功能api不太可能会出错的
dracularking 2012-12-20
  • 打赏
  • 举报
回复
引用 9 楼 lianshaohua 的回复:
引用 5 楼 dracularking 的回复: readlen会不对吗?按理这么简单的一个功能api不太可能会出错的 的确不对。readlen和写入buffer中的数据长度不一致,也就是: 有的时候返回了readlen,但没有读到数据。
根据javadoc,返回的字节数和实际读取到的字节应该是一致的,不管读取过程是以何种方式结束的,包括读完length字节,检测到EOF,异常产生。 楼主不妨贴下调试截图。
ztenv 2012-12-19
  • 打赏
  • 举报
回复
引用 1 楼 wrwuvemq 的回复:
你有没有尝试过查看一下read后buff里面的数据? 看下真实的长度是多少,如何真的不对,你去看一下你的服务器端发送数据的时候有没有 flush(); 如果还不行我就没办法了。
看了buf的数据,不对,从客户端抓包了,抓到了服务器发送过来的所有的包(所有的分片组合到一起是一个完整的服务器的包) 非常感谢你的关注
wrwuvemq 2012-12-19
  • 打赏
  • 举报
回复
你有没有尝试过查看一下read后buff里面的数据? 看下真实的长度是多少,如何真的不对,你去看一下你的服务器端发送数据的时候有没有 flush(); 如果还不行我就没办法了。
代码转载自:https://pan.quark.cn/s/c50a500cf555 在当今全球经济迅猛增长的背景下,通讯技术的持续进步使得个人之间的联系日益紧密,因此个人对其联系人信息的有效管理变得尤为重要。在此需求下,通讯录应运而生,各式各样的通讯录应用正不断为人们的生活带来便利。通讯录管理软件主要用于处理日常生活中的同学、朋友等联系人的信息编辑,帮助用户随时获取所需联系人的全部资料。这款通讯录管理系统操作简便,用户能够通过该系统轻松完成添加、检索、更新、移除等基本的管理任务。软件的操作界面通常可以隐藏在屏幕的边缘区域,当用户的鼠标移至该区域时,操作界面会自动显现,用户仅需输入关键词(如联系人姓名)即可快速找到所需的通讯录数据。 【Java课程设计-通讯录系统】是一款基于Java编程语言开发的个人通讯录管理工具,其目的是协助用户高效地处理和查找联系人信息。该系统是在JDK 1.7.0和NetBeans 6.9.1集成开发环境中构建的,提供了添加、检索、修改和删除联系人等核心功能,旨在为用户提供流畅的操作体验。 ### 一、需求分析 1. **基本功能**:系统需具备存储联系人姓名、电话、电子邮箱等核心数据的能力,并支持用户执行新增联系人、查找特定联系人、编辑现有联系人资料以及移除无用联系人等操作。 2. **搜索功能**:用户通过输入联系人姓名的关键字,系统能迅速定位到对应的联系人记录。 3. **界面友好**:界面设计需简洁明了,操作直观易用,软件窗口支持隐藏于屏幕边缘,并在鼠标接近时自动展示。 4. **数据保存**:系统必须实现联系人数据的持久化存储,确保程序关闭后数据不会丢失。 ### 二、任务分析 1. **主界面设计**:开发一个用户友好的主界...

62,620

社区成员

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

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