JAVA socket读取速度慢于Python

2 投票
1 回答
558 浏览
提问于 2025-04-17 23:21

我正在尝试通过TCP套接字从Python服务器读取数据。为了这个目的,Python客户端已经写好了,而我需要为Android编写代码。我在JAVA中尝试了不同的方法,但我发现我写的JAVA代码在读取套接字时非常慢。

在某些情况下,我会覆盖缓冲区,因为我只关心接收到的字节数,而不关心实际的数据。

以下是Python客户端中套接字读取的代码片段:

        buffer_len = 0
        print str(tcp.response_len) + " start  " + str((time.time()-timeOrigin)*1000)
        while True:
            buffer_len += len(self.sock.recv(4096))
            print str(buffer_len) + " of " + str(tcp.response_len)
            if buffer_len >= tcp.response_len:
                break

以下是我在JAVA中尝试的几种方法:

            while (totalRead < RS.getResponse_len()) {
                                    //dataInputStream is of type DataInputStream
                int bytesRead = dataInputStream.read(buffer, totalRead, RS.getResponse_len() - totalRead);
                Log.d("Response", "Total read : " + totalRead + " of " + RS.getResponse_len());
                if (bytesRead < 0) {
                    throw new IOException("Data stream ended prematurely");
                }
                totalRead += bytesRead;
            }

使用小缓冲区:

                while (totalRead < RS.getResponse_len()) {
                int bytesRead = dataInputStream.read(buffer, 0, 4096);

                Log.d("Response", "Total read : " + totalRead + " of " + RS.getResponse_len());
                if (bytesRead < 0) {
                    throw new IOException("Data stream ended prematurely");
                }
                totalRead += bytesRead;
            }

我还尝试过使用readFully而不是read,但读取速度仍然很慢。

然后我尝试使用ReadableByteChannel读取数据,如下所示:

            ByteBuffer lenBuf = ByteBuffer.allocate(4096);
            //SocketChannel.open();
            ReadableByteChannel channel = Channels.newChannel(client.socket.getInputStream());
            int bytesRead = 0;
            while (totalRead < RS.getResponse_len()) {
                bytesRead = channel.read(lenBuf);
                lenBuf.clear();
                Log.d("Response", "Total read : " + totalRead + " of " + RS.getResponse_len());
                totalRead += bytesRead;
            }

但我没有看到读取速度有明显的改善。

你能指出我代码中的错误,或者给我一些更快读取的替代方案吗?

谢谢。

1 个回答

0

我不太明白RS.getResponse_len()这个函数具体做什么。我只能希望它不是通过循环来计算长度。不过,你第二段代码有一个改进之处。你原来的代码会分配足够的缓冲区大小来容纳整个响应的长度。你可以把缓冲区的大小用作Response_len()。这样你可以写成:

byte[] buffer = new byte[RS.getResponse_len()];
int totalRead = 0;
while(totalRead<buffer.length) {
    int bytesRead = dataInputStream.read(buffer,totalRead,buffer.length-totalRead);
    if(bytesRead<0) throw new IOException("Data stream ended prematurely");

    totalRead+=bytesRead;
}

你提到你要读取14MB的数据。在这种情况下,你需要先读取到一个较小的缓冲区,然后处理这个缓冲区。

如果你只是想读取内容而不做其他处理,可以试试这个:

byte[] buffer = new byte[10240]; // 10Kb buffer
BufferedInputStream bis = new BufferedInputStream(dataInputStream);
int totalBytesToRead = RS.getResponse_len();
while(totalBytesToRead>0) {
    int bytesRead = bis.read(buffer);
    if(bytesRead<0) throw new IOException("Data stream ended prematurely");
    totalBytesToRead -= bytesRead;
}

撰写回答