100分求救!!socket的InputStream.readyFully(byte[] b)一直阻塞不能返回??

lvyuanfang 2007-07-19 11:26:36
1.某些时候,socket取得的InputStream.readFully在收到6个字节的头之后,接收剩余字节时,readFully方法好像一直阻塞,而服务端已经发送成功。。
而有时又是好的。。
2.发送时每次抓包看到都是一个包分两次发,第一次只发1个字节,剩下的再一次发完。
没有设置接收缓冲和发送缓冲,也没有设置其他的任何socket选项。。有一个专门的接收线程,收到一个整包后放入一个队列中。。
郁闷啊。。

代码如下:
logger.info("######## ClientSocketFacade Thread start...");
while (connected) {

// logger.info("Tsapi start receiving packet from server");

try {

logger.debug("Begin receiving: " + System.currentTimeMillis());
if(!atomicBool.get()) {
try {
lock.lock();
if (cond != null && atomicBool != null) {
atomicBool.set(true);
if (lock.hasWaiters(cond)) {
cond.signalAll();
}
logger.debug("Wakeup invoker thread.");
}
} finally {
lock.unlock();
}
}
logger.debug("After unlock.");

// 接收6个字节的头
byte[] msgHeader = new byte[6];
this.input.readFully(msgHeader);

MessageHeader mh = new MessageHeader(new LEDataInputStream(msgHeader), null);

mh.receive();

logger.debug(mh);// 这个地方能打印出来

if (mh.getTag1() != TsapiConstants.MESSAGE_TAG1 || mh.getTag2() != TsapiConstants.MESSAGE_TAG2) {
logger.error("Invalid message from tsapi server");
continue;
}
// 接收固定长度的数据封装成流
byte[] content = new byte[mh.getLength()];
this.input.readFully(content);// 比如头是6个字节,包体的长度为100字节,这个地方有时候就一直阻塞,不返回,导致接收线程一直阻塞,而服务端显示已经发送成功了。。

EventWrapper eventWrapper = new EventWrapper(mh, content);

// modified by lvyf 2006.10.24
// 用concurrent包中的阻塞队列
this.streamAdapter.getEventQueue().offer(eventWrapper);

logger.debug("Receive bytes: " + content.length);

logger.debug("End received: " + System.currentTimeMillis());
} catch (IOException e) {
logger.fatal("run() - Receive message from tsapi server failed", e);
this.close();
this.invokeListeners();
break;
}

}

...全文
877 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
lvyuanfang 2007-08-03
  • 打赏
  • 举报
回复
readFully的用法我知道,客户端是java,服务端是linux上的c++。情况是这样的:
每个收到的包由6个字节的包头和不定长字节的包体组成,我就先readFull(byte[6]),然后6个字节的包头中有包体的长度,我按照这个长度来readFully(byte[包体长度]),但是我在readFully(包体)之前,打印的available字节数是我要收的包体长度(available长度表示能无阻塞接收的字节数),这就说明,socket缓冲区是收到了的,但是我readFully(包体)的时候好像被其他线程打断。下面就好像不执行了。。这个地方会被打断吗??
另外一个问题:我想把socket收发改成nio阻塞的方式,但是我测了一下性能,数据如下:
接收10000*206byte=1.96mbyte的4次平均时间:
nio:85489ms
io: 85089ms
好像nio还不如io的性能??

有哪位高人能类似的经验,请指教,不胜感激。。
我的java客户端在applet里运行。。
fool_leave 2007-07-25
  • 打赏
  • 举报
回复
first thing first
readFully这个方法不是InputStream的吧。它是DataInputStream的

建议,在使用非InputStream方法时一定要搞清楚,封装类都作了什么额外的工作

readFully实际上是对read方法的封装

byte buf[]=new byte[1024];
dis.readFully(buf);
这句话的意思是,流会向buf里添写数据,直到把1024个数据填写完毕才返回。如果你发送的数据不超过1024个,他就会一直等待在read处。
所以你看到的现象是完全正常的

建议把readFully改为read,不要想当然的用这个方法。很危险
KingNE 2007-07-25
  • 打赏
  • 举报
回复
帮顶
lvyuanfang 2007-07-21
  • 打赏
  • 举报
回复
我是客户端接收时调用readFully(接收固定长度的字节,类似linux上MSG_WAIT标志位),服务端是linux上的c++程序。。
我发送给服务端都flush的。。抓包都是只发送一个字节,然后发送剩余的。。


sszhangy 2007-07-20
  • 打赏
  • 举报
回复
我也经常遇到这样的问题,结果发现,发送端没调用flush()函数,楼主尝试一下。
masse 2007-07-20
  • 打赏
  • 举报
回复
调用一下flush...试试
weihthchk 2007-07-20
  • 打赏
  • 举报
回复
不知道readFully是怎么运作的,这个方法不会一直阻塞到收到EOF为止吧?

62,614

社区成员

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

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