2012-11-24 113 views
2

我做在客戶端寫一些東西到服務器一個簡單的TCP服務器/客戶端應用程序,它然後回顯到客戶端。但是,當我試圖讀取服務器在客戶端回顯什麼時,我遇到了一些問題。讀取和寫入套接字

string s; 
while((n = read(socketFD[0],readBuf, BUFFER_SIZE)) > 0){ 
    cout<<"\nBytes read: "<<n<<endl; 
    s.append(readBuf, n); 
} 
cout<<"\nTest after read\n"; 

我寫16 KB的文本到服務器。當我在客戶端閱讀時,我每次閱讀4 KB。

從這段代碼的輸出是:

Bytes read: 4096 

Bytes read: 4096 

Bytes read: 4096 

Bytes read: 4046 

讀取調用似乎它的完成從套接字讀取後,再也不離開環路阻斷。我怎樣才能解決這個問題?

編輯:這是處理連接的客戶端的服務器中的代碼。

if((childpid = fork()) == 0){ 
    close(listenFD); 
    while ((n = read(connectFD, buf, BUFFSIZE)) > 0){ 
    cout<<"\nBytes read: "<<n<<endl; 
    write(connectFD, buf, n); 
    } 
    cout<<"\nTest after read\n"; 
    exit(0); 
} 

這個輸出是:

Bytes read: 4096 

Bytes read: 4096 

Bytes read: 4096 

Bytes read: 4046 

Test after read 

相比,在客戶端的代碼有什麼不同在這裏?爲什麼讀取調用塊不像在客戶端中那樣?

+0

什麼是'readArr'?當服務器關閉連接時,循環應該退出 - 'read()'將返回0來指示EOF。 – Barmar

+0

這是一個拼寫錯誤,應該是readBuf – Carlj901

+1

這是行不通的,因爲readBuf不是C++字符串或C字符串。 C字符串需要以null結尾,而'read'不會這樣做,因爲它可以用於非字符串的數據。 – Barmar

回答

0

讀取調用在從套接字讀取後似乎阻塞,並且永遠不離開循環。我怎樣才能解決這個問題?

簡短的回答,在收到所有數據後不要致電read。當你收到你想收到當時的數據來檢測

編寫代碼,如果是這樣,退出循環。你必須實際執行某種協議。

s+=readBuf; 

這不可能是正確的。它如何知道要添加到s的數據字節數?

+0

你可以在帖子中查看添加的代碼嗎?爲什麼我會得到不同的結果? – Carlj901

+0

看看'n'的值。如果它是零,那是因爲另一端關閉了連接。如果它是'-1',請檢查'errno'以瞭解爲什麼'read'返回。 –

+0

因此,讀取中的返回值0總是意味着連接的另一端已關閉? – Carlj901

0

你會想要麼pollselect,如果你不希望把讀取循環在另一個線程,這樣你可以看到是否有存在於隊列的東西,而不從實際閱讀。

+0

那麼讀取系統調用總是阻塞? – Carlj901

+0

在阻塞套接字上,一個'read'調用將被阻塞,直到至少有一個字節被讀取或發生錯誤或連接關閉。如果您願意,可以使套接字不阻塞。 –

0

下面是對Python中套接字非常好的介紹的摘錄。它是Python,是的,但是它暴露了C-Socket API,所以你的上下文中寫的是真實的。你可以在這裏閱讀:http://docs.python.org/dev/howto/sockets.html

本節關於「使用套接字」告訴你到底是什麼問題,你正在觀察。它討論了recv函數,但是它轉換爲文件描述符上的read函數。

但是,如果您打算重新使用套接字進一步傳輸,您需要認識到套接字上沒有EOT。我再說一遍:如果一個套接字發送或recv在處理0個字節後返回,則連接已中斷。如果連接沒有中斷,你可以永遠等待recv,因爲套接字不會告訴你沒有更多的東西要讀(現在)。現在,如果你仔細想一想,你會意識到套接字的基本真理:消息必須是固定長度(yuck),或者是分隔(聳肩),或者表明它們多長時間(好得多),或者通過關閉連接結束。這個選擇完全屬於你,(但是有些方法比其他方式更爲合適)。