【问题标题】:How to receive only one packet from tcp socket quickly java如何快速从tcp套接字接收一个数据包java
【发布时间】:2016-12-31 22:45:22
【问题描述】:

远程 Tcp 服务器设备一次发送 8 个字节的数据,并且速度相对较快(但不是非常快)。无论如何,我想接收 8 个字节并在给定的 8 个字节上执行。但是,我似乎正在接收这些 8 个字节的倍数的字节数组,我的计数(在代码中)是 8 个字节的倍数,长度从 16 到 120+ 个字节不等。

检查 Wireshark,远程 Tcp 服务器似乎正确地发送了 8 个字节并且没有将它们组合起来。这向我表明套接字的读取速度太慢,因此我不希望将 8 个字节的间隔背靠背组合在一起。一个例子是:

8bytes-8bytes-16bytes-8bytes-8bytes-56bytes。

这里是数据流入的时间戳。只需 10 毫秒。

(13:44:23.210) 00h 10h 01h 06h FFh 3Ah FFh FFh
(13:44:23.290) 00h 10h 01h 06h FFh 3Fh FFh FFh
(13:44:23.300) 00h 10h 01h 06h FFh 44h FFh FFh

如何在确保没有倍数的 8 字节数据的同时尽可能快地有效地从端口读取?

下面的代码是一段读取未知大小的数据并将其发送回 NetworkManager 进行进一步处理的段。我曾尝试使用不同的流以希望获得所需的效果,但两种流都不能确保这一点。

    private class Receive extends Thread {

        private InputStream inputStream;
        private DataInputStream dataInputStream;
        private BufferedInputStream bufferedInputStream;
        private ByteArrayOutputStream byteArrayOutputStream;

        public void run() {
            if (DEBUG) Log.d(TAG + " \"" + name + "\"", String.valueOf(getId()) + ":receive run.");
            bundle = new Bundle();
            buffer = new byte[1024];
            try {
                bufferedInputStream = new BufferedInputStream(socket.getInputStream());
            } catch (IOException ioException) {
                Log.d(TAG + " \"" + name + "\"", String.valueOf(getId()) + ":IOException", ioException);
            }
            while (connected && !closed) {
                if (DEBUG) Log.d(TAG + " \"" + name + "\"", String.valueOf(getId()) + ":retry read.");
                try {
//                    socket.setSoTimeout(timeout);
                    int count = bufferedInputStream.read(buffer);
                    byteArrayOutputStream = new ByteArrayOutputStream(count);
                    if (count == -1) {
                        networkManager.stopTcpNetwork(name);
                        closed = true;
                        Log.d(TAG + " \"" + name + "\"", String.valueOf(getId()) + "Connection Lost?!?!");
                    } else {
                        if (DEBUG) Log.d(TAG + " \"" + name + "\"", String.valueOf(getId()) + ":call back." + " Count: " + String.valueOf(count));
                        byteArrayOutputStream.write(buffer, 0, count);
                        bundle.putByteArray(name, byteArrayOutputStream.toByteArray());
//                        bundle.putByteArray(name, buffer);
                        message = networkManager.obtainMessage();
                        message.what = Messages.MESSAGES_TCP_DATA.getInt();
                        message.setData(bundle);
                        networkManager.sendMessage(message);
                    }
                } catch (SocketTimeoutException socketTimeoutException) {
                    if (DEBUG) Log.d(TAG + " \"" + name + "\"", String.valueOf(getId()) + ":no data yet.");
                } catch (Exception exception) {
                    Log.d(TAG + " \"" + name + "\"", String.valueOf(getId()) + ":Exception", exception);
                }
            }
        }
    }

【问题讨论】:

  • buffer = new byte[8]; ?
  • @greenapps 这是否有效地加快了读取操作?
  • 你为什么这么认为?你为什么要问?
  • 您看到的情况在使用 TCP 时是很正常的。这称为缓冲。在缓冲区中读取 1000 个字节,然后每次循环处理 8 个字节,直到缓冲区为空或剩余不到 8 个字节,这有什么困难?
  • 如果一次只需要八个字节,则一次只读取八个字节。很难看出这里有什么奥秘。您应该为此使用DataInputStream.readFully()。你不需要ByyeArrayOutputStream

标签: java android sockets tcp inputstream


【解决方案1】:

套接字只是在数据被读入缓冲区之前缓冲数据。正如其他人指出的那样,正确的答案是要么从套接字读取所有内容,要么只从套接字读取预期数量的字节。

不管怎样,项目增长了,需要引入的数据也增长了。话虽如此,最简单的方法是将数据发送回另一个线程以进行本地缓冲,然后最终循环通过潜在消息(检查是否完整)并继续处理。

所以,希望这对其他人有所帮助.. 如果没有,哎呀,对不起。 感谢所有评论和帮助的人!

【讨论】:

  • “最直接的答案”发表于 2016 年 8 月 24 日 20:07 的评论中,这里没有任何内容可以真正回答这个问题。
猜你喜欢
  • 2011-09-09
  • 2012-12-28
  • 2013-07-04
  • 1970-01-01
  • 2014-12-14
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
  • 2014-10-05
相关资源
最近更新 更多