Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/182.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android N-DataOutputStream.writeInt()行为已更改?_Java_Android_Sockets - Fatal编程技术网

Java Android N-DataOutputStream.writeInt()行为已更改?

Java Android N-DataOutputStream.writeInt()行为已更改?,java,android,sockets,Java,Android,Sockets,我有一个处理套接字连接的简单类: public class SimpleConnection { // Socket, input and output streams protected Socket mSocket; protected DataInputStream mIn; protected DataOutputStream mOut; public boolean createConnection(String ip, int port

我有一个处理套接字连接的简单类:

public class SimpleConnection {

    // Socket, input and output streams
    protected Socket mSocket;

    protected DataInputStream mIn;

    protected DataOutputStream mOut;

    public boolean createConnection(String ip, int port) {
        SocketAddress socketAddress = new InetSocketAddress(ip, port);
        mSocket = new Socket();
        try {
            mSocket.connect(socketAddress, 3000);
            mIn = new DataInputStream(mSocket.getInputStream());
            mOut = new DataOutputStream(mSocket.getOutputStream());
        } catch (IOException e) {
            return false;
        }

        return true;
    }

    public boolean sendData(byte[] data) {
        try {
            mOut.writeInt(data.length);
            mOut.write(data);
            mOut.flush();
        } catch (Exception e) {
            e.printStackTrace();
            closeSocket();
            return false;
        }
        return true;
    }
}
这一直有效到安卓N。使用安卓N,
mOut.writeInt(data.length)
只发送四个零,而不是
data.length
的长度。这会导致服务器误解消息,导致整个程序无法工作

通过将整数转换为字节[4],我能够“修复”这个问题:

byte[] len = Utilities.intToByteArray(data.length);
mOut.write(len);
将显示intToByteArray

我的问题是:
writeInt
为什么不再在安卓N上工作了?在其他Android版本上,此代码运行良好

我使用的是最新的Android Studio,包括Java 8、gradle 2.1.3和Android buildtools 24.0.2

编辑: 接收部件在Qt中的外观如下所示:

void readData(QTcpSocket* client_) {
  while (client_->bytesAvailable()) {
    int expected_length_;
    QDataStream s(client_);
    s >> expected_length_;
    qLog(Debug) << expected_length_;

    // Read data with expected_length_
    QBuffer buffer_;
    buffer_.write(client_->read(expected_length_));
  }
}
这是两种变体的输出。。。因此,似乎
writeInt()
可以像预期的那样工作,但为什么它可以用于Android bytesAvailable()>=4,然后才从套接字读取整数呢。这解决了这个问题,
writeInt()
变体现在也可以工作了

但为什么行为会突然改变

分析流量后,我发现
writeInt()
刷新数据

它完全按照你说的做了
DataOutputStream
未被缓冲,并且它下面没有
BufferedOutputStream
,因此
writeInt()
向网络写入了四个字节

过早地

TCP中不存在“过早”这样的事情。TCP不保证打包或分段。如果要控制这种所谓的“过早刷新”,请使用
mOut=newdataoutputstream(newbufferedoutputstream(Socket.getOutputStream())
并在写入数据后自行刷新

所以有些帧只有一个或两个字节,这就是为什么bytesAvailable只有1个字节

  • 这是你的主要问题。您误用了
    available()
    。它不是消息结束指示器。请参阅Javadoc
  • 您也没有检查是否确实读取了长度单词的四个字节
  • 据我所知,您也没有检查是否已收到所有字节的数据
一般来说,您必须循环,直到获得预期的所有内容

服务器代码QDataStream只读取一个或两个字节的int。添加
if(客户机->字节可用()<4)后中断并等待更多数据,它可以工作。但我仍然不明白为什么行为会改变


它可以随时改变。你的代码中断了,因为它依赖于几个无效的假设。

你可以保证数组的长度实际上不是
0
?声称内部方法被破坏是一项相当严重的指控。是的,
data.length
15
,而不是
0
。这令人难以置信。如果这个方法被破坏,那么JDK的一半将无法工作。显示您的接收代码。我确切地知道Qt的zip,但肯定
s>>预期长度是否进行ASCII转换?您还没有显示实际读取了那么多字节的部分,这是大多数此类代码的地方。在Java中,您需要使用
DataInputStream.readFully()
,或相应的循环:否则您将与发送方不同步。我编辑了服务器端代码<代码>预期长度为0,因此
缓冲区没有数据。问题是,服务器代码和客户机代码可以运行数月甚至数年。只有安卓N,它突然停止工作。安卓N在发送整数的四个字节之前是否刷新了数据?谢谢你的回答,我现在明白我做错了什么。我更改了
mOut
,按照您的建议添加了
BufferedOutputStream
,并正确检查了服务器代码中的长度。哇,感谢您的回答!就连我也面临着同样的问题(该应用程序是针对棉花糖n,而不是牛轧糖)。这真是太好了!
▶ nc -p 1234 -l 0.0.0.0 | xxd
00000000: 0000 000f 0815 1001 aa01 0808 8edb 0110  ................
00000010: 0118 00                                  ...