繁体   English   中英

Java DataOutputStream不会写入所有消息(TCP套接字)

[英]Java DataOutputStream doesnt write all messages ( TCP Socket )

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

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

每个方法将字节数组发送到客户端

如果我只调用其中的2个,则一切正常,客户端将获取所有已发送的字节数组。 但是,如果我将它们中的全部三个都称为第一个和第二个到达客户端,则以下方法的顺序无关紧要。 但是服务器说所有的都发送了。 使用write(byte[] b, int off, int len);向客户端iam write(byte[] b, int off, int len); 全部使用方法包中的长度也很有意义。 奇怪的是:

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

编辑:

假设我要发送3个登录响应

该方法给了我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(); 客户端连续连续3次接收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);
        }
    }
}

谢谢!

DataOutputStream和TCP不会丢失数据。

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

根据注释中的协议描述,在这种情况下,应使用DataInputStream.readFully()

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

如果我调用sendLoginResponse(); 客户端连续连续3次接收2个字节数组,但服务器表示已发送3次。

这是因为TCP是面向流的协议。 意味着它不知道或不在乎您的消息如何分隔。 在TCP中没有单独消息的概念,只是字节流,并保证字节顺序得以保留。

因此,当发送方调用三个write ,这三个字节数组将简单地通过连接进行连接,并以相同的顺序到达接收方,但是接收方不一定需要进行三个read即可获取所有字节,即使它确实需要三readread不一定给您传递到每个对应write的相同字节数组。

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

// Client code for reading individual messages from a TCP connection

byte type = din.readByte();

// Read the message length, little-endian.
// We cannot use din.readShort because it's big-endian
int lenLo = din.read();
int lenHi = din.read();
short len = (short)(lenLo | (lenHi << 8));
byte [] body = new byte[len];
din.readFully(body);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM