简体   繁体   English

DataInputStream readInt()仅工作一次

[英]DataInputStream readInt() works only once

I'm using Java sockets to make two android devices communicating with the same app. 我正在使用Java套接字使两个Android设备与同一个应用程序进行通信。 The communication protocol is: 通信协议为:

1. client sends packet size S
2. client sends byte array with size S

I'm using DataOutputStream and writeInt() to write the size as raw value on the stream. 我正在使用DataOutputStreamwriteInt()writeInt()为流上的原始值。 The server then reads this value whit DataInputStream and readInt() . 然后,服务器使用DataInputStreamreadInt()读取此值。 The problem is that readInt() reads the right value only for the first packet. 问题在于readInt()仅为第一个数据包读取正确的值。 The second time this method returns a random int . 此方法第二次返回随机int

Relevant code snippets: 相关代码段:

Client side: this method is called on top of a working TCP connection with the server 客户端:在与服务器之间有效的TCP连接之上调用此方法

public void write(byte[] packet)
{
    try
    {
        dataOutputStream.writeInt(packet.length);
        dataOutputStream.flush();

        dataOutputStream.write(packet);
        dataOutputStream.flush();        
    }
    catch (IOException e)
    {
        Log.e(ERROR_TAG, "write() failed", e);
    }
}

Server side: this is the loop that reads data 服务器端:这是读取数据的循环

...

int readBytes = 0;
int packetSize = 0;

while (true) {
    byte[] buffer = new byte[NET_BUFF_SIZE];

    try // first it reads the packet size from packet header
    {
        packetSize = dataInputStream.readInt();
    } catch (IOException e) {
        Log.e(ERROR_TAG, "readInt() failed", e);
        return;
    }

    while (readBytes < packetSize) {
        try {
            int readResult = dataInputStream.read(buffer);

            if (readResult != -1) {
                readBytes += readResult;
            } else {
                break;
            }
        } catch (IOException e) {
            Log.e(ERROR_TAG, "read() failed", e);
            break;
        }
    }
}

So, when the client calls write() to send the second packet, the server reads a wrong size from the stream. 因此,当客户端调用write()发送第二个数据包时,服务器从流中读取了错误的大小。

DataOutputStream and DataInputStream are initialized in this way: DataOutputStreamDataInputStream以这种方式初始化:

// Server
inputStream = clientSocket.getInputStream();
dataInputStream = new DataInputStream(inputStream);

// Client
outputStream = socket.getOutputStream();
dataOutputStream = new DataOutputStream(outputStream);

What I am missing? 我缺少什么?

The server reads as much data as is available. 服务器读取尽可能多的数据。 It may read more than what's included in the packet that the client sent, or it may read less. 它读取的内容可能超过客户端发送的数据包中包含的内容,或者读取的内容可能更少。 With the loop you seem to handle the case when read returns less than what you expect, but you also should handle the case when it reads more than what's included in the packet. 通过循环,您似乎可以处理read返回的结果少于您期望的情况,但当它读取的内容大于数据包中包含的内容时,您也应该处理情况。 Remember that TCP is stream-oriented: even though you call flush there's no guarantee that the remote application receives the data in separate calls to read . 请记住,TCP是面向流的:即使您调用flush也不能保证远程应用程序在单独的read调用中接收到数据。

The DataInput interface defines a method called readFully that reads exactly as many bytes as you want, no more and no less. DataInput接口定义了一个称为readFully的方法,该方法可读取所需的字节数,不多也不少。 This means you can remove the loop, simplifying the code to read a packet to this: 这意味着您可以删除循环,从而简化代码以读取数据包:

packetSize = dataInputStream.readInt();
dataInputStream.readFully(buffer, 0, packetSize);

On your server side you should re-initialize the readBytes variable after the while(true) loop: 在服务器端,您应该在while(true)循环之后重新初始化readBytes变量:

while (true) {
     readBytes = 0;
     ....
}

All the best. 祝一切顺利。 A debugger would help you spot this problem sooner. 调试器将帮助您更快地发现此问题。

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

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