2015-12-12 86 views
0

我有一個關於TCP連接中的非阻塞套接字的問題。將TCP客戶端套接字設置爲非阻塞:服務器vs客戶端

我已經實現了兩個C++類,一個用於TCP服務器和一個客戶端。服務器有兩個套接字文件描述符,一個用於服務器,一個用於客戶端。客戶端有一個套接字文件描述符。

我的服務器異步運行和我的客戶在一個固定的速度運行。因此,我想要有一個無阻塞的套接字來將數據從客戶端發送到服務器s.t.客戶端可以以固定速率發送數據而不會停止,並且服務器會同時讀取所有已緩衝的數據。

所以我的問題是:如果我在客戶端或服務器類中將客戶端套接字設置爲非阻塞,是否有所作爲?(使用fcntl(this->newsockfd_, F_SETFL, fcntl(this->newsockfd_, F_GETFL, 0) | O_NONBLOCK),其中this->newsockfd_是這兩類客戶的套接字文件描述符)

我在PROGRAMM嘗試這樣做,它似乎像客戶端套接字設置爲非阻塞的客戶端類沒有做的伎倆,但將其設置在服務器級別上。但是,我不明白爲什麼這應該有所作爲。

+1

在什麼區別?將套接字設置爲非阻塞意味着套接字讀取,寫入和其他套接字操作將立即返回。然後,您必須準備好處理沒有數據傳輸的情況,因爲操作通常會因爲沒有可讀取的數據或出站網絡緩衝區已滿而被阻塞等。 –

回答

-1

由於您的客戶端只發送數據,非阻塞設置不會影響它。根據套接字編程上出色的beej.us guide,只有對accept()recv()的調用受到非阻塞設置的影響。由於只有您的服務器正在調用這些服務器代碼,因此您會看到服務器代碼發生更改如果你的客戶端收到數據,那麼非阻塞設置會影響它,你將不得不使用select()來檢查是否有數據並相應地讀取數據。

+0

此答案錯誤,因爲發送可以阻止以及。 beej說很多功能塊。接受()塊。所有recv()函數都會阻塞。 accept和recv函數不是很多,只有2個可以阻止的函數的例子。如上所述,發送也可以阻止。 –

+0

您的引用沒有說明您聲稱的內容,而第三方網站不是規範性參考。你應該引用* man *頁面或Posix,它們也不這樣說。 – EJP

1

如果你的套接字被設置爲非阻塞模式,你將會得到。它永遠不會阻止。但這並不意味着你的api電話會成功。

有些緩衝區正在後臺使用,如果它們已滿,這意味着在阻塞模式下套接字將被阻塞,您將得到一個返回碼EWOULDBLOCK,這意味着您的發送已失敗。這意味着您基本上必須等待緩衝區清空然後重試。

你儘管服務器率以均勻的速率發送接收的想法,是不可能的。您不能讓客戶端以固定的速率發送。 TCP的整體思想是在客戶端和服務器之間進行不斷的協商,速度將取決於網絡條件。擁塞等等。

移動到非阻塞套接字會產生一些問題。您必須檢測到發送失敗,您必須檢查套接字是否可再次寫入,您必須存儲您嘗試發送的字節,並在套接字再次變爲可寫入時立即重新嘗試發送。

有客戶端和與阻塞和非阻塞套接字工作之間的服務器上有很大的區別的。在我看來,非阻塞套接字更難以處理。您需要選擇api,並且超時很可能會檢測到所有可能的套接字狀態。在阻塞套接字的情況下,你可以在一個線程中使用一個套接字,如果套接字阻塞,它就是阻塞的線程。如果你的GUI是在不同的線程上,GUI將會響應。