2012-07-15 126 views
2

我正在使用Windows套接字爲我的應用程序(winsock2.h)。由於阻塞套接字不讓我控制連接超時,所以我使用了非阻塞套接字。在發送命令之後,我正在使用shutdown命令來刷新(我必須)。我的超時時間是50ms,我想知道的是如果要發送的數據如此之大,是否存在僅發送一部分數據或根本不發送任何信息的風險?在此先感謝...發送後非阻塞TCP套接字和沖洗?

hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    u_long iMode=1; 
    ioctlsocket(hSocket,FIONBIO,&iMode); 
    connect(hSocket, (sockaddr*)(&sockAddr),sockAddrSize); 
    send(hSocket, sendbuf, sendlen, 0); 
    shutdown(hSocket, SD_BOTH); 
    Sleep(50); 
    closesocket(hSocket); 
+0

嗯,我敢肯定的是,連接超時工作的很好的阻止套接字以及 - 我該做的客戶端線程內所有的時間 - 如果斷開連接,循環輪connect()的嘗試和睡眠(2000 ),不斷重試連接,直到一個成功。連接超時反正是不相關的connect()成功後,插座寫,所以我假定你的意思寫超時的一種形式?如果是這樣,我從來沒有嘗試過這樣的事情 - 我不使用連接/斷開連接協議(除了瀏覽器/ HTTP!),因爲性能不佳(特別是在高延遲鏈接上)。 – 2012-07-15 10:47:22

+0

您可以使用select()超時阻塞模式連接。您不必調用shutdown()來刷新。 TCl不會丟失數據,否則互聯網將無法工作,例如這個論壇,亞馬遜,谷歌等。你的問題是基於假前提。 – EJP 2012-07-15 10:59:51

+0

您是「選擇」插座狀態並檢查斷開連接嗎?我想盡可能快地發送數據。另外兩種可能的情況是:服務器等待時間過長以接受連接或接收。所以連接和寫作都應該在最長50ms內完成,因爲時間對我而言非常重要。我必須同時刷寫寫入和讀取流,因爲服務器不斷向我發送不必要的大數據,並且我的網絡連接有限。事實上,我甚至不希望從服務器:) – theGD 2012-07-15 11:00:56

回答

-2

感謝EJP和馬丁,現在我創建了第二個線程來檢查。同樣在我發佈的代碼中,我添加了「counter = 0」在「發送」行後刪除關機。它現在就像我想要的那樣工作。它從來沒有等待50ms以上:)真的非常感謝

unsigned __stdcall SecondThreadFunc(void* pArguments) 

{

while(1) 
{ 
    counter++; 
    if (counter > 49) 
    { 
     closesocket(hSocket); 
     counter = 0; 
     printf("\rtimeout"); 
    } 

    Sleep(1); 
} 
return 0; 

}

+0

我真的不希望因此而受到指責。它不回答你的問題。它不符合你的想法。所有在航班中的數據仍將被髮送,然後關閉信號將被髮送。它沒有實現任何類型的超時。 – EJP 2016-01-25 21:21:07

0

非阻塞TCP套接字,並在之後的沖洗送?

有沒有這樣的事情,刷新TCP套接字。

由於阻擋插座沒有讓我控制連接超時

假。您可以在阻擋套接字上使用select()

我正在使用非阻塞的。

非sequitur。

在發送命令後,我正在使用shutdown命令來刷新(我必須)。

您不需要和shutdown()不刷新任何內容。

我超時爲50ms

爲什麼?發送數據的時間取決於數據的大小。明顯。對於發送使用固定超時沒有任何意義。

而我想知道的事情是,如果要發送的數據如此之大,是否存在只發送一部分數據或根本不發送任何數據的風險?

在阻塞模式下,您提供給send()的所有數據將盡可能發送。在非阻塞模式下,如果可能,將會發送返回值send()所表示的數據量。無論哪種情況,如果發送失敗,連接將被重置。無論您添加的超時機制如何,都不能改變其中的任何一種情況:具體而言,在超時後異步關閉套接字只會導致關閉被附加到正在發送的數據上。它將而不是導致發送被中止。

您的代碼不會通過任何人已知的代碼審查。沒有錯誤檢查;睡眠完全沒有意義;並在關閉之前關閉是多餘的。如果睡眠旨在實現超時,則不會。

我想盡可能快地發送數據。

你不行。 TCP實現流量控制。對此你完全無能爲力。你受到接收者的限制。

另外,2種可能情況是:服務器等待太久接受連接

有沒有這樣的情況。客戶端可以完成連接的服務器不斷呼籲accept().之前,如果你想實現一個連接超時比約一分鐘的默認短,使用select().

或接收。

你可以做些什麼:見上文。

因此,連接和寫入應該在最大50ms內完成,因爲時間對我而言非常重要。

參見上文。對需要可變時間的操作實施固定的超時是沒有意義的。對於連接超時而言,50ms太短。如果這是一個真正的問題,您應該保持連接打開,以便連接延遲只發生一次:實際上,您應該儘可能長時間保持TCP連接打開。

我來刷新寫入和讀取流

你不能。 TCP中沒有任何操作會刷新讀取流或寫入流。

因爲服務器一直向我發送不必要的大數據,而且我的網絡連接有限。

另外非sequitur。如果服務器向您發送數據,則必須讀取它,否則您將停止服務器,而這與刷新自己的寫入流沒有任何關係。

其實我甚至不從服務器

運氣不好要一個字節。你必須閱讀它。 [如果您使用的是BSD Unix,則可以關閉套接字進行輸入,這會導致服務器的數據被丟棄,但這在Windows上不起作用:它會導致服務器重置連接。]

+0

哦代碼是不完整的,我貼的代碼是唯一的第二個線程。如果握手3的方式完成,並要發送的數據是從我的電腦(以線)我只是在計時器歸零。所以它確實工作。另一件事是,select在幾秒鐘內接受超時而不是毫秒。最後,據我記得,我的意思是從緩衝區清除數據。我現在只是沒有延遲選項... – theGD 2016-01-28 00:31:49

+0

你的方法的工作原理是沒有失敗,但它不會做你聲稱需要的:強制執行寫入超時。它所做的就是無償地關閉一個工作插座。 Re'另一件事',你錯了。 'select()'以'timeval'結構的形式接受一個超時,該結構包含秒和微秒的字段。 'shutdown()'仍然不會刷新一個套接字,它只能*表示刷新套接字發送緩衝區。只有正常傳輸或復位才能做到這一點。 – EJP 2016-01-28 02:29:57