Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.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中读取tcp流的最有效方法_Java_Tcp - Fatal编程技术网

在Java中读取tcp流的最有效方法

在Java中读取tcp流的最有效方法,java,tcp,Java,Tcp,我不得不修改一些客户端代码,因为通信协议没有正确定义 我假设来自服务器的tcp消息将以新行终止,所以我使用reader.readLine()读取数据 现在我被告知情况并非如此,而是消息的前4个字符是消息长度,然后我必须阅读消息的其余部分 做这件事最有效、最明智的方法是什么 我的总体想法如下: 创建一个4字符数组 读入前4个字符 确定消息长度 创建消息长度的新数组 读入新数组 下面是一个代码示例(读取器是在别处创建的BufferedReader): 我知道如何做到这一点,但我必须担心字符缓冲区没有

我不得不修改一些客户端代码,因为通信协议没有正确定义

我假设来自服务器的tcp消息将以新行终止,所以我使用reader.readLine()读取数据

现在我被告知情况并非如此,而是消息的前4个字符是消息长度,然后我必须阅读消息的其余部分

做这件事最有效、最明智的方法是什么

我的总体想法如下:

  • 创建一个4字符数组
  • 读入前4个字符
  • 确定消息长度
  • 创建消息长度的新数组
  • 读入新数组
  • 下面是一个代码示例(读取器是在别处创建的BufferedReader):

    我知道如何做到这一点,但我必须担心字符缓冲区没有被填满吗?如果是这样,我应该如何处理这种情况?

    Java中的字符用于文本数据。你确定协议真的这样定义了消息的长度吗?更可能是前四个字节代表32位长度

    如果你和C或C++开发人员交谈,他们可能会使用“char”作为“字节”的同义词。 编辑:好的,根据评论:

    我将创建一个方法,该方法接受一个
    读取器
    和一个计数,并反复调用
    read()
    ,直到它读取了正确数量的数据,或者抛出了一个异常。大概是这样的:

    public static String readFully(Reader reader, int length) throws IOException
    {
        char[] buffer = new char[length];
        int totalRead = 0;
        while (totalRead < length)
        {
            int read = reader.read(buffer, totalRead, length-totalRead);
            if (read == -1)
            {
                throw new IOException("Insufficient data");
            }
            totalRead += read;
        }
        return new String(buffer);
    }
    
    您应该检查当他们希望发送少于1000(或超过9999)个字符时会发生什么情况,尽管…

    Java中的字符用于文本数据。你确定协议真的这样定义了消息的长度吗?更可能是前四个字节代表32位长度

    如果你和C或C++开发人员交谈,他们可能会使用“char”作为“字节”的同义词。 编辑:好的,根据评论:

    我将创建一个方法,该方法接受一个
    读取器
    和一个计数,并反复调用
    read()
    ,直到它读取了正确数量的数据,或者抛出了一个异常。大概是这样的:

    public static String readFully(Reader reader, int length) throws IOException
    {
        char[] buffer = new char[length];
        int totalRead = 0;
        while (totalRead < length)
        {
            int read = reader.read(buffer, totalRead, length-totalRead);
            if (read == -1)
            {
                throw new IOException("Insufficient data");
            }
            totalRead += read;
        }
        return new String(buffer);
    }
    

    您应该检查当他们想发送少于1000(或超过9999)个字符时会发生什么…

    呃。。。Java中的
    char
    不是16位的Unicode吗?我认为你做得不对,用字符来表示从网络中输出的字节。您可能应该考虑改用
    java.nio
    包中的
    之类的东西

    如果您知道单个消息的最大大小,那么就不能阻止您创建单个缓冲区,将四个字节读入缓冲区,将它们解析为
    int
    左右,然后以该大小重新读取,覆盖缓冲区的内容


    更新:上述假设协议是二进制的,并且
    char
    的使用是“C-ism”。如果协议实际上是文本,并且初始的4个字符长度是一个填充整数(在某些情况下,我猜是10?),比如“0047”或“6212”,那么其他方法可能更好,不必从字节到字符。

    呃。。。Java中的
    char
    不是16位的Unicode吗?我认为你做得不对,用字符来表示从网络中输出的字节。您可能应该考虑改用
    java.nio
    包中的
    之类的东西

    如果您知道单个消息的最大大小,那么就不能阻止您创建单个缓冲区,将四个字节读入缓冲区,将它们解析为
    int
    左右,然后以该大小重新读取,覆盖缓冲区的内容


    更新:上述假设协议是二进制的,并且
    char
    的使用是“C-ism”。如果协议实际上是文本,并且初始的4个字符长度是一个填充整数(在某些情况下,我猜是10?),比如“0047”或“6212”,那么其他方法可能更好,为了不必从字节到字符。

    关于问题的一部分,即一旦确定了需要读取一定数量的字符,以下习语在java.io.Readers中很常见:

    int lengthToRead = getRequiredReadLength(); // Left as exercise to reader :-)
    char[] content = new char[lengthToRead]
    int from = 0;
    while (lengthToRead > 0)
    {
       try
       {
          int nRead = reader.read(context, from, lengthToRead);
          if (nRead == -1)
          {
             // End of stream reached before expected number of characters
             // read so handle this appropriately - probably throw an exception
          }
          lengthToRead -= nRead;
          from += nRead;
       }
       catch (IOException e)
       {
          // Handle exception
       }
    }
    
    由于
    read
    调用保证返回一个非零结果(调用阻塞直到某些数据可用,到达流的末尾(返回-1)或引发异常),因此此while循环确保只要流能够提供字符,您就可以读取所需的任意多个字符


    一般来说,当一次从读卡器中请求多个字符时,应该知道不能保证实际提供了多个字符,并且应该始终检查返回值以查看发生了什么。否则,您将不可避免地在某个时刻遇到bug,流的某些部分将“消失”。

    关于问题的一部分,即一旦确定了需要读取一定数量的字符,以下习语在java.io.Readers中很常见:

    int lengthToRead = getRequiredReadLength(); // Left as exercise to reader :-)
    char[] content = new char[lengthToRead]
    int from = 0;
    while (lengthToRead > 0)
    {
       try
       {
          int nRead = reader.read(context, from, lengthToRead);
          if (nRead == -1)
          {
             // End of stream reached before expected number of characters
             // read so handle this appropriately - probably throw an exception
          }
          lengthToRead -= nRead;
          from += nRead;
       }
       catch (IOException e)
       {
          // Handle exception
       }
    }
    
    由于
    read
    调用保证返回一个非零结果(调用阻塞直到某些数据可用,到达流的末尾(返回-1)或引发异常),因此此while循环确保只要流能够提供字符,您就可以读取所需的任意多个字符


    一般来说,当一次从读卡器中请求多个字符时,应该知道不能保证实际提供了多个字符,并且应该始终检查返回值以查看发生了什么。否则,您将不可避免地在某个时刻出现错误,流的某些部分将“消失”。

    协议是基于16位Java“char”还是8位C“char”?它在另一端作为字符串读取,前4个字符是长度。我假设它们是16位Java字符。我会给服务器端工作的人发电子邮件