Java DataOutputStream不会写入所有消息(TCP Socket)

时间:2016-10-13 16:24:51

标签: java sockets tcp stream dataoutputstream

在我的客户端 - 服务器应用程序中,我发现了一个奇怪的错误我有以下方法:

sendLoginResponse();
sendPlayerList();
sendCurrentLevelState();

每个方法都向客户端发送一个字节数组

如果我只调用其中的2个,那么一切正常,客户端获取所有发送的字节数组。但是,如果我打电话给他们所有3个,只有第一个和第二个到达客户端,以下方法的顺序无关紧要。但服务器说所有这些都是发送的。使用。写入客户端iam write(byte[] b, int off, int len);方法 所有包装内的长度也是有意义的。 这有一个奇怪的地方:

如果我在第二个方法之后添加Thread.sleep(1000);,则第三个方法现在在睡眠后到达客户端。我也尝试在每次写调用后刷新DataOutputStream,但这没有用。

编辑:

所以,假设我发送3个Login-Response

Method给了我byte []:

public byte[] getLoginResponse(int playerID){
    byte[] msg = new byte[4];
    short shortMsgLength = 4;
    byte[] msgLength = shortToBytes(shortMsgLength);
    msg[0] = 2;
    msg[1] = msgLength[0];
    msg[2] = msgLength[1];
    msg[3] = (byte) playerID;
    return msg;
}

private byte[] shortToBytes(short value) {
    byte[] returnByteArray = new byte[2];
    returnByteArray[0] = (byte) (value & 0xff);
    returnByteArray[1] = (byte) ((value >>> 8) & 0xff);
    return returnByteArray;
}

发送方法:

private void sendLoginResponse() {
    try{
        byte[] msg = rfcObject.getLoginResponse(playerID);
        out.write(msg,0,msg.length);
    }catch(Exception e){
        System.err.println(e.getMessage());
        System.exit(0);
    }
}

因此,如果我连续三次调用sendLoginResponse();,则客户端只接收2个字节数组,但服务器表示已经发送了3次。如果我添加

Thread.sleep(1000); `after the second Method-Call, everything works fine..`

读取消息的客户端在线程中运行:

public void run(){
    while(true){
        try {
            byte[] data = new byte[MAX_DATA_SIZE]; // MAX_DATA = 255
            byteCount = in.read(data);

        } catch (IOException ex) {
            handleExceptionError(ex);
        }
    }
}
谢谢你!

2 个答案:

答案 0 :(得分:0)

DataOutputStream和TCP不会丢失数据。

在这种性质的问题中几乎不变,问题出在接收端。您可能假设`read()'填充缓冲区,并忽略它返回的计数。

根据评论中的协议说明,您应该在这种情况下使用DataInputStream.readFully()

byte type = din,readByte();
int length = din.readShort();
byte[] data = new byte[length];
din.readFully(data);

答案 1 :(得分:0)

  

如果我调用sendLoginResponse();连续三次,客户端只收到2个字节数组,但服务器说已经发送了3次。

这是因为TCP是面向流的协议。这意味着它不知道或关心您的邮件是如何分隔的。 TCP中没有单独消息的概念,只是一个字节流,保证保留字节顺序。

因此,当发送方调用三个write时,三个字节数组通过连接简单连接,并以相同的顺序到达接收方,但接收方不一定需要三个{{1}获取所有字节,即使它确实需要三个readread也不一定会为您提供传递给每个相应read的相同字节数组。

您的消息已经具有从字节流中获取单个消息的必要信息:

write