2014-08-29 71 views
0

我正嘗試使用Linux中的C網絡編程讀取和寫入套接字。我分別在客戶端和服務器程序中成功調用「寫入」和「讀取」。使用讀取和寫入功能的C中的套接字錯誤

我很難理解的部分是,在我的客戶端程序中,我在服務器上循環並調用write 5次不同的時間,我循環並調用read 5次不同的次數。

這是預期的輸出:

MSG: I got your message MSG: I got your message MSG: I got your message MSG: I got your message MSG: I got your message 

這是實際的輸出:

MSG: I got your messageI got your messageMSG: I got your messageI got your messageMSG: I got your messageMSG: MSG: 

正如你所看到的預期輸出和實際輸出是不同的。看起來客戶端能夠在實際發送之前調用「寫入」兩次。

這是我的客戶端代碼

for(int i=0;i<5;i++) 
{ 
    int n = write(ssocket.socketFileDescriptor,"I got your message",18); 
    cout<<n<<" number of bytes written."<<endl; 
    if (n < 0) socketError("ERROR writing to socket"); 
} 

這是服務器代碼:

void* run(void* arg) 
{ 
    ServerSocket* ss = (ServerSocket*)arg; 
    //while(true) 
    for(int i=0;i<5;i++) 
    { 
     char buffer[256]; 
     bzero(buffer,256); 
     int n = read(ss->newsockfd,buffer,256); 
     printf("MSG: %s",buffer); 
    } 
    close(ss->newsockfd); 
} 

這是除了問題,下面這是過時的,在這一點上。

我缺少一個調用刷新或什麼的?

Simulate Java's Thread class in C++

+1

您假定TCP可以傳輸大於一個字節的消息。它不能 - 它是一個字節/八位字節的STREAMING協議,並且不知道一個字節之上的消息邊界。如果您想傳輸更大,更復雜的消息,則需要TCP上的協議。這個問題有無數次 - 這麼多,我不能看着:) – 2014-08-29 21:08:54

+0

如果你使用的TCP套接字,然後發送的所有內容連接成一個流,當它被讀取時,你會得到什麼是可用的直到緩衝區大小)。您需要插入自己的消息邊界並在接收器中解析流。 – molbdnilo 2014-08-29 21:12:04

+0

所以我打開wireshark並確認每個'寫'調用實際上創建了它自己的數據包。 所以這意味着閱讀是雙倍的。這是我看到'讀',我說在我的代碼中讀取256個字節。 – Matthew 2014-08-30 19:56:18

回答

2

你的客戶端和服務器只是沒有協調。客戶端儘可能快地將消息寫入5次,並且服務器儘可能快地讀取5次。在您的示例輸出中,顯然在第一次撥打read()時,客戶端發送了兩次消息,在第二次撥打read()時,又發送了兩次。你最多可以有256個字符,每次你調用它時,它只會嘗試讀取當前在緩衝區中的任何內容。如果客戶在那個時候發送了多封郵件,read()只會抓住一切。

您通常需要某種類型的同步,例如,發送一條消息後,客戶端會在發送第二條消息之前等待服務器發送"OK"或類似內容。除此之外,如果您的通信格式非常簡單,則可以使用某種類型的消息結束標記(例如換行符),以便服務器區分它們。

+0

或者只是在兩邊添加緩衝(服務器和客戶端)。 – 2014-08-29 21:12:12

+0

是的!我想添加緩衝,但我不完全知道如何做到這一點。我正在嘗試創建一個類似於Java的系統,以及所有使用BufferedFileReader構建的系統或其他... 你如何做緩衝?另外,說我想發送更多的256個字符沒有響應?我怎麼做?我假設這個套接字使用TCP,所以我不應該承認無論如何,雖然正確? – Matthew 2014-08-29 21:25:40

+0

@Matthew:你最好的選擇是使用許多第三方網絡庫之一。實現緩衝並不是那麼困難,但也並非完全微不足道。你可以通過每次read()一個字符來實現一個窮人的版本,直到你碰到行尾字符,接收未知長度的行。使用單字符的系統調用效率相對較低,但除非您正在編寫大容量服務器,否則網絡可能會成爲瓶頸。 – 2014-08-29 21:29:47