線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2672
推到 Plurk!
推到 Facebook!

關於完成端口,WSASend的問題

答題得分者是:aftcast
mistakee
一般會員


發表:1
回覆:1
積分:0
註冊:2015-02-16

發送簡訊給我
#1 引用回覆 回覆 發表時間:2015-03-30 22:59:23 IP:111.249.xxx.xxx 未訂閱
各位前輩好
請教關於重疊I/O,WSASend的問題

小第將待發送的資料寫入TMemoryStream,假設寫入資料為1~5000
再連續WSASend 5次,每次資料長度1000
本來想說,接收到的資料也會是5次,每次1000筆
但實際上卻"不一定",有時會接收6次,但接收到的資料總長度是對的
例如某次僅接收200筆,下一次接收到的起始值,會從201筆開始,最後會多接收一次800筆補足
設定每筆傳送長度1000,也沒超過MSS,為什麼會將我的包裹拆開來傳送
而且之後每次接收都會被平移

但若稍微延遲一下每次WSASend的時間,比如說每WSASend一次,在Memo上印幾個字母
這樣接收到就不會出錯,即接收5次,每次1000筆
想請教前輩,這是怎樣的情形,謝謝各位
-----------------------------------------------------------------------------------------------------------------------------------------
舉例
傳送端:
依序傳送 Send1 Send2 Send3 Send4 Send5
傳送筆數 1000 1000 1000 1000 1000
傳送資料 1~1000 1001~2000 2001~3000 3001~4000 4001~5000
-------------------------------------------------------------------------------------------------------------------------------------------
預期接收端:
Recv1 Recv2 Recv3 Recv4 Recv5
接收筆數 1000 1000 1000 1000 1000
接收資料 1~1000 1001~2000 2001~3000 3001~4000 4001~5000
-------------------------------------------------------------------------------------------------------------------------------------------
實際接收端:
Recv1 Recv2 Recv3 Recv4 Recv5 Recv6
接收筆數 1000 1000 200 1000 1000 800
接收資料 1~1000 1001~2000 2001~2200 2201~3200 3201~4200 4201~5000

[code cpp]
bool TIOCP::PostSend(CIOCPContext *pContext, CIOCPBuffer *pBuffer)
{
pBuffer->nOperation=OP_WRITE;
DWORD dwBytes;
DWORD dwFlags=0;
WSABUF buf;
buf.buf=pBuffer->buff;
buf.len=pBuffer->nLen;
if(::WSASend(pContext->s,&buf,1,&dwBytes,dwFlags,&pBuffer->ol,NULL)!=NO_ERROR)
{
if(::WSAGetLastError()!=WSA_IO_PENDING)
return false;
}
::EnterCriticalSection(&pContext->Lock);
pContext->nOutstandingSend ;
::LeaveCriticalSection(&pContext->Lock);
return true;
}
[/code]

aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2015-03-31 09:09:51 IP:114.32.xxx.xxx 訂閱
不錯喔,使用iocp來寫socket,題外話,未來看是否有機會可以合作看看。我需要人才,哈哈。
關於 tcp 之 socket 有一個最易被忽略但極重要的概念 : tcp 是streaming base的通訊協定!
這意味著什麼? 就是 tcp 本身的封包是以stream的方式被處理。這樣的特性導致tcp的lib並不知道(也無法知道,也不想知道) 如何是完整的訊息。所謂的完整的訊息可能由數個封包組成,但到底是幾個? tcp lib 是不管的。於是更進一步的來說,即使你分5次來送封包,接收端也沒一定要用5次來接收完成,原因是既然tcp的規範是streaming based的,封包的"組裝"就該是更上層的通訊要處理,比如http會處理。但你個人以tcp為基準來收資料時,你就要自己去組裝。
簡言之,你所觀察到的是tcp socket的正常特性。當然,若你故意把send的離散一點送,"原則上"會比較如你預期,送5收5。但這不實際且穩健。「永遠不能依賴 tcp 收到的次數等於送出的」! 接著你該怎麼做?
自訂你自己的frame的規格,一般來說有二類,一類是header帶長度,表接下來該是幾個bytes。第二類是frame本身有頭有尾,意味著收到某尾端的bytes時表示完整訊息達成。以上是通訊程式要學的進階課程,書上少寫,因為這是「江湖一點訣,說破不值錢」。

觸類旁通的補充 : udp 是 message based。

------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
mistakee
一般會員


發表:1
回覆:1
積分:0
註冊:2015-02-16

發送簡訊給我
#3 引用回覆 回覆 發表時間:2015-03-31 09:54:32 IP:111.249.xxx.xxx 未訂閱
謝謝前輩的指教
目前我也是以自訂Frame來解決
只是不懂及很疑惑是不是我哪裡寫錯造成
難道一定要自己再重組嗎?
經由前輩提點有所了解
謝謝


系統時間:2024-04-26 0:29:03
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!