簡體   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