各位大神,請教下,TServerSocket用這個的時候接收資料,最后一次的資料有時可以收到,有時收不到,不知道是資料的問題還是TServerSocket這里沒處理好
void __fastcall TForm1::srvrsckt1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
//void *Buffer;
char *c_data = new char[Socket->ReceiveLength() + 1];
AnsiString s_temp;
TMemoryStream *stream = new TMemoryStream();
stream->SetSize(Socket->ReceiveLength());
stream->Position = 0;
Socket->ReceiveBuf(stream->Memory, Socket->ReceiveLength());
stream->Read(c_data, stream->Size);
//stream->SaveToFile("1.txt");
mmo1->Lines->Add(AnsiString(c_data));
delete stream;
delete c_data;
}
uj5u.com熱心網友回復:
一般ReceiveBuf到陣列,陣列寫到MemoryStream吧,全部寫完以后注意MemoryStream的Position 。可以先SendText一個長度字串,比如"L8192",收到L開頭代表后面是發送流的長度,然后SendStream發送流,
讀的時候if(!bHasLength)就讀取長度字串,bHasLength=true。else回圈ReceiveBuf讀取流(當剩余長度>0),比如每次讀取1K,流太長了一次讀取可能會有問題。
uj5u.com熱心網友回復:
你可以試一下,我也剛接觸TServerSocket 。uj5u.com熱心網友回復:
回圈ReceiveBuf的時候也許可以適當延時若干毫秒,還可以設定超時break退出回圈。uj5u.com熱心網友回復:
來看看
uj5u.com熱心網友回復:
發送方可以先SendText一個長度字串,比如IntToStr(fs->Size),Sleep若干毫秒,然后SendStream發送流。接收方OnRead的時候,
if(!bHasSize)
就讀取長度字串,bHasSize=true。
else
回圈ReceiveBuf讀取流(當剩余長度>0),比如每次讀取32K,每次ReceiveBuf的回傳值是實際讀取的位元組數,或者沒讀到為-1。
還有一點要特別注意,OnRead事件處理函式是會重入的,在一個OnRead函式呼叫中回圈讀取流的時候,OnRead函式又會被呼叫執行,只要設定一個變數,碰到這種情況直接return就可以了。
還可以設定一個Timer,超時用變數標志從回圈讀取中退出。
可以用一個Memo來除錯輸出:
Size: 119182
reading...
remain: 119182
get: 4096
remain: 115086
return
get: 24576
remain: 90510
get: -1
return
remain: 90510
get: 24576
remain: 65934
get: 12288
remain: 53646
return
get: 24576
remain: 29070
return
get: 24576
return
remain: 4494
get: 4494
Done!
BCB 6.0本機除錯每次ReceiveBuf最多24K,CB2010是8K。兩機局域網除錯每次ReceiveBuf一般不超過8K。
uj5u.com熱心網友回復:
發送方可以先SendText一個長度字串,比如IntToStr(fs->Size),Sleep若干毫秒,然后SendStream發送流。————
這樣不好,兩次發送之間需要Sleep。
先SendBuf發送一個長度int就可以了,buf強制地址轉換為int* 。
uj5u.com熱心網友回復:
@ooolinux 首先先謝謝你的回答,我會試下在srvrsckt1ClientRead事件里回圈讀取的,發送這里我控制不了,因為是設備自動發送,不知道設備是怎么樣的發送機制,這里我只能控制我這邊接收的,再次感謝。uj5u.com熱心網友回復:
發送、接收流之前,先發送、接收流的長度,也是比較常用的做法了。uj5u.com熱心網友回復:
發送較大的流的話,用ReceiveBuf只接收一次肯定是不完整的,因為每次ReceiveBuf能收到的量都有限。uj5u.com熱心網友回復:
如果發送時先SendText一個長度字串,比如IntToStr(fs->Size),Sleep若干毫秒,然后SendStream發送流;接收時中間也要Sleep,不過毫秒數要小于發送中間Sleep的毫秒數。如果不Sleep,資料容易串起來,導致接收錯誤。
不過長度可以用SendBuf發送一個int,就不用Sleep了,接收時代碼稍微復雜一點。
uj5u.com熱心網友回復:
可以這樣,采取一來一回的方式:客戶端發送"getfile filename"字串;服務器端打開檔案流,發送流的大小資訊;
客戶端收到流的大小,發送"ready"字串;服務器端發送流;
客戶端(回圈)接收流。
uj5u.com熱心網友回復:
void __fastcall TForm1::srvrsckt1ClientRead(TObject *Sender,TCustomWinSocket *Socket)
{
//void *Buffer;
char *c_data = new char[Socket->ReceiveLength() + 1];
AnsiString s_temp;
TMemoryStream *stream = new TMemoryStream();
stream->SetSize(Socket->ReceiveLength());
stream->Position = 0;
Socket->ReceiveBuf(stream->Memory, Socket->ReceiveLength());
stream->Read(c_data, stream->Size);
//stream->SaveToFile("1.txt");
mmo1->Lines->Add(AnsiString(c_data));
delete stream;
delete c_data;
}
uj5u.com熱心網友回復:
沒試過INDY么?那個控制元件比較簡單好用。轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/42677.html
標籤:網絡及通訊開發
上一篇:關于某DLL COFF頭問題
下一篇:資料處理
