简体   繁体   English

Java AsynchronousSocketChannel读取操作

[英]Java AsynchronousSocketChannel read operation

I'm using the java AsynchronousSocketChannel from nio2 in my project. 我在我的项目中使用了nio2的java AsynchronousSocketChannel I'm using oracle jdk 1.7.0_80 on ubuntu 14.04 too. 我也在ubuntu 14.04上使用oracle jdk 1.7.0_80。

My project is a server that processes binary data. 我的项目是一台处理二进制数据的服务器。 The code calls the read operation recursively in the completed method of the CompletionHandler anonymous class, like this: 该代码在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);
    }
}

Where the variable swap is a ByteBuffer instance. 其中变量swap是ByteBuffer实例。

Apparently, everything works well. 显然,一切正常。 But, there is a packet whose total size is 3832 bytes, when the server receive this whole packet, without segments, there is no problem. 但是,有一个总大小为3832字节的数据包,当服务器接收到没有分段的整个数据包时,就没有问题。 However, sometimes this packet is divided in two or more parts (TCP segments). 但是,有时将此数据包分为两个或更多部分(TCP片段)。 eg: The size of first segment is 2896 bytes and the size of second is 936 bytes. 例如:第一段的大小为2896字节,第二段的大小为936字节。

The last segment doesn't have a header, this is breaking my algorithm. 最后一段没有标题,这破坏了我的算法。 I would like know, is there a way to do the API calls the "completed" method only after reading the whole packet? 我想知道,是否只有在读取整个数据包之后,API才能调用“ completed”方法?

I have increased the SO_RCVBUF to 64K, but it doesn't work. 我已经将SO_RCVBUF增加到64K,但是它不起作用。

I would like know, is there a way to do the API calls the "completed" method only after reading the whole packet? 我想知道,是否只有在读取整个数据包之后,API才能调用“ completed”方法?

No, there is no way to do this. 不,没有办法做到这一点。

The TCP protocol can break up your stream of bytes in packets of arbitrary size. TCP协议可以分解任意大小的数据包中的字节流。 The application-level protocol that you use on top of TCP must not rely on messages always being sent completely in one TCP packet. 在TCP之上使用的应用程序级协议一定不能依赖总是在一个TCP数据包中完全发送的消息。

You must design your application-level protocol in such a way that it can deal with messages arriving broken up in packets of arbitrary size. 您必须以一种可以处理以任意大小的数据包分解的消息的方式设计应用程序级别协议。

One common way to do this is to prefix application-level messages by a length field. 一种常用的方法是在应用程序级别的消息前面加上长度字段。 For example, an application-level message consists of a field of 4 bytes that contain the length of the rest of the message. 例如,应用程序级消息由4个字节的字段组成,该字段包含消息其余部分的长度。 When you receive a message, you first receive the length, and then you should keep on receiving until you have received that many bytes, which you can then assemble into an application-level message. 收到消息时,首先要接收长度,然后继续接收,直到收到那么多字节为止,然后可以将其组合成应用程序级消息。

The AsynchronousSocketChannel API cannot re-assemble application-level messages automatically for you, because it does not know anything about your application-level protocol. AsynchronousSocketChannel API无法为您自动重新组合应用程序级消息,因为它对您的应用程序级协议一无所知。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM