【问题标题】:DataInputStream with sockets... missing bytes?带有套接字的 DataInputStream... 缺少字节?
【发布时间】:2012-06-19 16:45:11
【问题描述】:

在我的项目中,我使用DataOutputStreamDataInputStream 使用带有线程的套接字发送和接收字节。

客户

public void run(){
    while(isRunning) {//which is true upon connection of the socket to the server
         if(scanner.hasNext()){ // I use a scanner to test the program
             dos = new DataOutputStream(new OutputStream(socket.getOutputStream));

             byte[] toServer = scanner.next().getBytes();
             dos.writeInt(toServer.length);
             dos.write(toServer);
         } 
    }
}

服务器

public void run(){
    while(isRunning){
        if(scanner.hasNext()){
              dis = new DataInputStream(new InputStream(socket.getInputStream));    
              int arrLength = dis.readInt();

              byte[] fromClient = new byte[arrLength];
              dis.read(fromClient, 0, fromClient.length);
              System.out.println("Your string is: " + new String(fromClient));
        }
    }
}

问题是,当我在服务器端打印出new String(fromClient) 时,单词/句子的第一个字符总是丢失。当我在客户端输入单词"Test" 时,服务器会打印出"est"。但是当我输入" Test"(开头有一个空格)时,服务器会打印出"Test"。我不明白怎么了?我的字节转换有问题吗?

【问题讨论】:

  • dos.writeInt(toServer) 必须是拼写错误,因为它无法编译。
  • 还有,客户端/服务器中的InputStream/OutputStream 错字
  • 是的,它们是拼写错误……抱歉。
  • 首先,应该可以使用dis.read(fromClient),尽管这不能解决问题
  • 另外,socket.getInputStream() 返回一个InputStream,所以new InputStream 没有意义。

标签: java multithreading sockets byte


【解决方案1】:

下面的代码对我有用。鉴于帖子中的拼写错误,我怀疑这不是正在运行的实际代码,而是一个近似值,并且这是真实代码中的错误。以下是一些需要注意的事项:

  • 如果你在readInt() 调用之后有一个dis.readByte();,那显然会切断主角。确保您的写入和读取完全对称。还要确保您的流链是对称的。

  • 如果您从另一个类获取流,请确保它本身没有执行任何读取方法。

  • 当前帖子正在执行 new InputStream()(和 OutputStream),由于它们是抽象的,因此无法编译。如果那里有缓冲,你需要确保你dos.flush();。然而,这会导致挂起,而不是部分输入。


String file = "/tmp/x";
DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));

String inputString = "Test";
byte[] toServer = inputString.getBytes();
dos.writeInt(toServer.length);
dos.write(toServer);

DataInputStream dis = new DataInputStream(new FileInputStream(file));
int arrLength = dis.readInt();

byte[] fromClient = new byte[arrLength];
dis.read(fromClient, 0, fromClient.length);
// works fine for me
assertEquals(inputString, new String(fromClient));

【讨论】:

  • 我回去工作后会试试这个!谢谢!编辑:在您的示例中,您使用 FileOutputStream 而不是获取套接字的 InputStream/OutputStream ... 这有关系吗?
  • 是的,它当然可能是@user979023。这更像是一个演示,我不认为你发布的代码是错误的——除了错别字。
  • 这是一个有效的套接字客户端/服务器@user979023。似乎工作正常:pastebin.com/hqnfd7Pg
  • 我非常讨厌维护由另一个人完成的代码...叹息...无论如何,@Gray,非常感谢您的帮助。您的示例代码对我有用。 +10000000!
  • @user979023 此代码假定 read() 填充缓冲区。您不能假设:请参阅 Javadoc。您需要使用 readFully()。
【解决方案2】:

您应该使用 readFully() 而不是 read(),并且您不应该为每次读取或写入都重新构建流。在套接字的生命周期中使用相同的流。另外扫描仪连接到什么?如果它附加到套接字,它将使用其中的数据。

【讨论】:

  • 我尝试使用readFully(),但不知何故程序停止工作......即使在调试模式下也是如此。
  • @user979023 那么扫描仪又连接到什么了?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多