【问题标题】:java BufferedReader specific length returns NUL charactersjava BufferedReader 特定长度返回 NUL 字符
【发布时间】:2010-04-22 01:47:14
【问题描述】:

我有一个 TCP 套接字客户端从服务器接收消息(数据)。 消息的类型为长度(2 个字节)+ 数据(长度字节),由 STX 和 ETX 字符分隔。

我正在使用 bufferedReader 检索前两个字节,解码长度,然后从同一个 bufferedReader 再次读取适当的长度并将结果放入 char 数组中。

大多数时候,我没有问题,但有时(收到的数千条消息中有 1 条),当尝试从阅读器读取(长度)字节时,我只得到其中的一部分,我的数组的其余部分是填充“NUL”字符。我想这是因为缓冲区还没有被填满。

char[] bufLen = new char[2];
_bufferedReader.read(bufLen);

int len = decodeLength(bufLen);

char[] _rawMsg = new char[len];
_bufferedReader.read(_rawMsg);

return _rawMsg;

我用几种迭代方式解决了这个问题:

  • 首先我测试了数组的最后一个字符:如果不是 ETX,我会从 bufferedReader 中一个一个读取字符,直到达到 ETX,然后重新开始我的常规程序。这 结果是我基本上会 DROP 一条消息。

  • 然后,为了仍然检索该消息,我会在我的“截断”消息中找到 NUL 字符的第一次出现,一次读取并存储其他字符,直到我到达 ETX,然后附加它们对于我的“截断”消息,确认长度是可以的。

它也有效,但我真的认为我可以做得更好,比如在读取缓冲区之前检查我需要的字符总数是否可用,但找不到正确的方法...

任何想法/指针?

谢谢!

【问题讨论】:

    标签: java sockets


    【解决方案1】:

    InputStream 读取方法可能会返回短读取;您必须检查返回值以确定读取了多少个字符,并在循环中继续读取,直到获得所需的数字。该方法可能会阻塞,但它只会阻塞直到 一些 数据可用,而不一定是您请求的所有数据。

    大多数人最终都会编写一个“readFully”方法,例如 DataInputStream,它会读取预期的数据量,或者抛出 IOException:

    static public int readFully(InputStream inp, byte[] arr, int ofs, int len) throws IOException {
        int                                 rmn,cnt;
    
        for(rmn=len; rmn>0; ofs+=cnt, rmn-=cnt) {
            if((cnt=inp.read(arr,ofs,rmn))==-1) { 
                throw new IOException("End of stream encountered before reading at least "+len+" bytes from input stream"); 
                }
            }
        return len;
        }
    

    【讨论】:

      【解决方案2】:

      这是我用于测试的示例服务器 主 rcv 的结构类似于

      while((chars_read = from_server.read(buffer)) != -1)
      {
          to_user.write(buffer,0,chars_read);
          to_user.flush();
      }
      

      实际的整个服务器在下面...

         public static void main(String[] args) throws IOException
         {
            try
            {
               if (args.length != 2)
                  throw new IllegalArgumentException("Wrong number of Args");
      
               String   host = args[0];
               int      port = Integer.parseInt(args[1]);
      
               Socket   s = new Socket(host,port);
      
               final Reader from_server = new InputStreamReader(s.getInputStream());
               PrintWriter to_server = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
      
               BufferedReader from_user = new BufferedReader(new InputStreamReader(System.in));
               final PrintWriter to_user = new PrintWriter(new OutputStreamWriter(System.out));
      
               to_user.println("Connected to " + s.getInetAddress() + ":" + s.getPort());
      
               Thread t = new Thread()
               {
                  public void run()
                  {
                     char [] buffer = new char[1024];
                     int chars_read;
                     try
                     {
                        while((chars_read = from_server.read(buffer)) != -1)
                        {
                           to_user.write(buffer,0,chars_read);
                           to_user.flush();
                        }
                     }
                     catch(IOException e)
                     {
                        to_user.println(e);
                     }
      
                     to_user.println("Connection closed by server");
                     to_user.flush();
                     System.exit(0);
                  }
               };
      
               t.setPriority(Thread.currentThread().getPriority() + 1);
               t.start();
      
               String line;
               while ((line = from_user.readLine()) != null)
               {
                  to_server.println(line);
                  to_server.flush();
               }
      
               //t.stop();
               s.close();
               to_user.println("Connection closed by client");
               to_user.flush();
            }
            catch(Throwable e)
            {
               e.printStackTrace();
               System.err.println("Usage : java TCPClient <hostname> <port>");
            }
         }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 2013-02-26
        • 2023-02-25
        • 1970-01-01
        相关资源
        最近更新 更多