2013-04-20 47 views
0

我用Java編寫的一個簡單的服務器,只是將一個整數連接的客戶端。我有一個用C編寫的客戶端,它連接到服務器並打印出接收到的Integer。發送INT - 奇怪的結果

我的問題是結果不一樣。大約有一半執行客戶端我得到正確的結果(234)的時代,但有時我得到8323072.

這是服務器:

class TCPServer { 
    public static void main(String args[]) throws Exception { 
    ServerSocket welcomeSocket = new ServerSocket(6789); 

    while(true) 
    { 
     Socket connectionSocket = welcomeSocket.accept(); 
     System.out.println("welcomeSocket.accept() called"); 
     DataInputStream inFromClient = new DataInputStream(connectionSocket.getInputStream()); 
     DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream()); 

     outToClient.writeInt(234); 
    } 
    } 

}

這是客戶端:

int main(int argc, char *argv[]) 
{ 
    if(argc != 4){ 
     printUsage(); 
     return; 
    } 

    char* serverIP = argv[1]; 
    char* serverPortC = argv[2]; 
    char* integerToSendC = argv[3]; 

    int serverPort = atoi(serverPortC); 
    int integerToSend = atoi(integerToSendC); 

    int socketDesc = socket(AF_INET, SOCK_STREAM, 0); 

    if(socketDesc < 0) { 
     printf("Error when creating socket\n"); 
     return; 
    } 

    struct sockaddr_in serverAddr; 
    serverAddr.sin_family = AF_INET; 
    serverAddr.sin_port = htons(serverPort); 
    inet_pton(AF_INET, serverIP, &serverAddr.sin_addr); 

    int connection = connect(socketDesc, (struct sockaddr*) &serverAddr, sizeof serverAddr); 

    if(connection < 0) { 
     printf("Error when establishing connection\n"); 
     return; 
    } 

    char intBuffer[4]; 

    if(recv(socketDesc, intBuffer, sizeof intBuffer, 0) == -1){ 
     printf("Error while receiving Integer\n"); 
    } 

    int receivedInt = ntohl(*((int *) &intBuffer)); 

    printf("Received int: %d\n", receivedInt); 

    close(socketDesc); 
} 

在此先感謝您的幫助!

編輯:那麼,到底 我做了這樣的事情,只是任何人誰具有相同的問題:

while(receivedBytes < 4){ 
    int readBytes = read(receiverSocket, &intBuffer, (sizeof intBuffer) - receivedBytes, receivedBytes); 
    receivedInteger += (intBuffer << (8*receivedBytes)); 
    receivedBytes += readBytes; 
} 
+1

可能可能是因爲多少字節分配'在Java和C及其相關子邊界int'。嘗試發送小號碼。如果Java爲int分配4個字節,則C分配2個字節。因此,該範圍在C – 2013-04-20 07:04:47

+0

中少得多,該數目是2 ** 16 * 127(即,第三個字節全1,底部的兩個全0) – 2013-04-20 07:08:55

+0

@LittleChild我本來也這麼認爲,但[DataOutputStream.writeInt](http://docs.oracle.com/javase/6/docs/api/java/io /DataOutputStream.html#writeInt(int))似乎很清楚發送四個字節,至少在32位運行時。 – WhozCraig 2013-04-20 07:09:37

回答

1

你可以確信你已經收到客戶端上的sizeof intBuffer字節?不,您不能,因爲recv()可能會返回較少的字節,然後請求。

國防部您的代碼迴路周圍recv()只要少字節隨後要求已收到,並沒有出現錯誤。

請注意,recv() ing 0字節表示連接已被另一端關閉。

還要確保服務器端網絡字節順序發送。

另外^ 2:在初始化變量(intBuffer這裏),至少在開發階段,會說:優化階段之前是個好主意。

+0

它不會擴展收到的值:'123'映射到網絡上的'00 00 00 7B'。收到的值「8323072」是「7F 00 00 00」。即使讀取1個字節,它也不應該是'7F'。 – 2013-04-20 20:22:52

+0

@ValeriAtamaniouk:大多數propably對方掛斷連接,'的recv()''與返回0',所以沒有錯誤消息記錄和'8323072'被打印出來'receivedInt'是簡單地作爲垃圾'intBuffer'在傳遞給'recv()'之前沒有初始化。 – alk 2013-04-22 15:14:41

+0

可能是,但是這並不完全匹配相應的部分源:DataOutputStream外殼在關閉之前發送4個字節。 – 2013-04-22 17:16:22

-1

你的問題可能是由於各種數據類型的子邊界。

在Java中,4字節分配給int,2字節分配給short
在C中,4字節用於long和2個字節用於int

這意味着Java intC longJava shortC int
現在這取決於你的優先事項在哪裏。

如果要執行Java中的激烈的數學計算和在插座結果發送到C,我建議你做Java int -> C long
如果你想只發送少量的數字和在C做了激烈的計算,做Java short - >C int轉換。

希望有幫助。

+1

在C中,在我的計算機中,4個字節用於'int'。 – johnchen902 2013-04-20 07:11:00

+0

請參見[DataOutputStream.writeInt](http://docs.oracle.com/javase/6/docs/api/java/io/DataOutputStream.html#writeInt(int))。看起來'writeInt'總是以big-endian寫入4個字節。只要它在C端作爲一個4字節的'int'被正確地重新組裝,我就會認爲這是正確的。 – WhozCraig 2013-04-20 07:11:43

+0

@WhozCraig我不用C編程。我只是指維基百科上的基本數據類型的大小,它表示C分配* 16位*(2字節)因此我的答案。如果答案中有錯誤,或者如果首先出錯,請告訴我。我將立即刪除它,以免混淆OP – 2013-04-20 07:13:57