我在我的项目中使用了来自nio2的java AsynchronousSocketChannel。我也在ubuntu14.04上使用oracle jdk 1.7.0_80。
我的项目是一个处理二进制数据的服务器。代码在CompletionHandler匿名类的completed方法中递归调用读取操作,如下所示:
private final CompletionHandler<Integer,AsynchronousSocketChannel> readHandler=new CompletionHandler<Integer,AsynchronousSocketChannel>(){
@Override
public void completed(Integer result,AsynchronousSocketChannel attachment) {
if(result<0){
attachment.close();
return;
}
attachment.read(swap, attachment, this);
}
}其中,变量swap是一个ByteBuffer实例。
显然,一切都运行得很好。但是,有一个数据包的总大小是3832字节,当服务器接收到这个完整的数据包时,没有分段,没有任何问题。但是,有时此数据包被分成两个或多个部分(TCP数据段)。第一段的大小是2896字节,第二段的大小是936字节。
最后一段没有报头,这破坏了我的算法。我想知道,有没有办法只在读完整个包之后才调用"completed“方法?
我已经将SO_RCVBUF调高到64K,但它不起作用。
发布于 2015-05-21 05:27:43
我想知道,有没有办法在读完整个包后才调用
方法?
不,没有办法做到这一点。
TCP协议可以将字节流分解为任意大小的数据包。您在TCP之上使用的应用层协议不能依赖于消息始终完全在一个TCP数据包中发送。
您必须以这样的方式设计应用程序级协议:它可以处理以任意大小的数据包分解的消息。
一种常见的方法是在应用程序级消息前面加上一个长度字段。例如,应用程序级消息由4个字节的字段组成,其中包含消息的其余部分的长度。当您接收消息时,您首先接收长度,然后您应该继续接收,直到您接收到那么多字节,然后您可以将这些字节组装成应用程序级消息。
AsynchronousSocketChannel应用程序接口不能自动为您重新组装应用程序级别的消息,因为它不了解您的应用程序级别协议的任何信息。
https://stackoverflow.com/questions/30360640
复制相似问题