[英]Java AsynchronousSocketChannel read operation
我在我的项目中使用了nio2的java AsynchronousSocketChannel
。 我也在ubuntu 14.04上使用oracle jdk 1.7.0_80。
我的项目是一台处理二进制数据的服务器。 该代码在CompletionHandler
匿名类的完成方法中递归调用读取操作,如下所示:
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字节。
最后一段没有标题,这破坏了我的算法。 我想知道,是否只有在读取整个数据包之后,API才能调用“ completed”方法?
我已经将SO_RCVBUF
增加到64K,但是它不起作用。
我想知道,是否只有在读取整个数据包之后,API才能调用“ completed”方法?
不,没有办法做到这一点。
TCP协议可以分解任意大小的数据包中的字节流。 在TCP之上使用的应用程序级协议一定不能依赖总是在一个TCP数据包中完全发送的消息。
您必须以一种可以处理以任意大小的数据包分解的消息的方式设计应用程序级别协议。
一种常用的方法是在应用程序级别的消息前面加上长度字段。 例如,应用程序级消息由4个字节的字段组成,该字段包含消息其余部分的长度。 收到消息时,首先要接收长度,然后继续接收,直到收到那么多字节为止,然后可以将其组合成应用程序级消息。
AsynchronousSocketChannel
API无法为您自动重新组合应用程序级消息,因为它对您的应用程序级协议一无所知。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.