全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1478
推到 Plurk!
推到 Facebook!

TClientSocket的問題??

答題得分者是:pental
kenbcb
中階會員


發表:171
回覆:129
積分:60
註冊:2003-07-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-11-21 14:53:04 IP:61.222.xxx.xxx 未訂閱
請問各位大大: 我有一堆資料超過1460,但是由多筆資料合成的,而其中一筆被分成二半不是我所訂的完整結構,要如何做才能完整處理? 我的一個完整結構是header+body ,捉header完後在由header內的大小的知Body要捉多少 ,     
 
void __fastcall TfrmAdmin::ClientSocket1Read(TObject *Sender,
      TCustomWinSocket *Socket)
{
  Front_Pack fBuf;
  unsigned char CRC,ckCRC;
  char Trail,buffer[2048]={0};
  
  while(1)
  {
    if(rWait == false)
    {
      Socket->ReceiveBuf((char *)buffer,sizeof(fBuf));
      memmove((char *)&fBuf,(char *)buffer,sizeof(fBuf));
    }
    if(fBuf.Leading != Header) return;
    
    if(Socket->ReceiveLength() < fBuf.Length) {rWait=true; return;}
    Socket->ReceiveBuf((char *)buffer,fBuf.Length sizeof(CRC) sizeof(Trail));
    rWait = false;
    
    其它處理
}
pental
初階會員


發表:3
回覆:48
積分:30
註冊:2003-09-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-11-22 14:12:01 IP:219.68.xxx.xxx 未訂閱
其中一筆被分成二半不是我所訂的完整結構 ------------------------------------------------ 你上述的這一段是什麼意思?是說你抓到的資料轉成你的結構的時候,只剩下一半的資料嗎?or something else ...
kenbcb
中階會員


發表:171
回覆:129
積分:60
註冊:2003-07-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-11-22 19:26:59 IP:61.229.xxx.xxx 未訂閱
對~另一半資料在第二個封包中,請問Clientsocket中的read事件是如何觸發的,我快要煩死了,都沒有詳細資料,都是簡略帶過...我想學好運用這些網路元件(TClientSocket,TServerSocket等),但在書店內都找不到, 都只是簡單使用..
pental
初階會員


發表:3
回覆:48
積分:30
註冊:2003-09-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-11-22 22:37:08 IP:211.76.xxx.xxx 未訂閱
我懂你的意思了! 我的處理方法是 我會在 header 的前面和後面加上一個特殊字元,比如說 header 的最前面是 0x01 ,最後面是 0x02,然後在定義一個陣列當Buffer, 然後每當觸發 SocketRead 的時候,就開始取資料,然後把收到的資料去判斷有沒有 0x01 或是 0x02 ,如果是 0x01 那就知道這個字元是 header 的開始,所以之後收到的資料都放到 Buffer 裡面去,這時候有可能你取回來的是一個完整的 header ,也可能是只有一半的 header,但沒關係,下一次在觸發 SocketRead 的時候,在去收資料,直到有找到 0x02,不是的話,就繼續放到Buffer裡面去,只到0x02那就知道這個是header的尾巴,這時候在 Buffer 裡面的就是一個完整的 header 囉!這樣子不管你的 header有多大,是否會被截掉,都可以正確的取得 header,然後你就可以依照 header 中所紀錄的 body 大小,在去進行 body 的接收。這是一個大概的觀念,實作部分就要你自己親自做做看囉!
pental
初階會員


發表:3
回覆:48
積分:30
註冊:2003-09-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-11-22 22:44:02 IP:211.76.xxx.xxx 未訂閱
另外你問到 ClientSocketRead 觸發的時機? 恩!應該是 ClientSocket 有收到資料的時候就會觸發,但是收到的資料量,不見得跟ServerSocket丟出來的是一樣,會根據網路的頻寬而有所差異,頻寬窄的話,ServerSocket丟出來的資料,ClientSocket需要觸發多次的 SocketRead 才收的完!這是我在網路傳輸方面的一些經驗!
kenbcb
中階會員


發表:171
回覆:129
積分:60
註冊:2003-07-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-11-24 11:17:21 IP:61.222.xxx.xxx 未訂閱
還是不行~有範例參考嗎 ^^???~    我所定的格式是一個格式(Header+body==>03 x x x 02),我要先抓Header(9byte),在依照header所指的大小來定body大小,但我送到header時知道body大小(假設200byte)了,但送來的封包body只有80byte,其它120byte在另一個封包(因為送來的資料大於1460,而剛好其中一筆記錄的body被拆成二部份),要如何做?? ,快教不出作業了^^|||~各位大大幫幫忙!    因為我目前做的可以處理我完整的(假設一個封包有二筆:hdeader+body+header+body)沒有問題,但如果收到(header+body+header+body(一半資料),另一半在別個封包(body(另一半)+header+body)就會只處理前面完整的,後面無法處理.  
 
void __fastcall TfrmAdmin::ClientSocket1Read(TObject *Sender,
      TCustomWinSocket *Socket)
{
  Front_Pack fBuf;
  unsigned char CRC,ckCRC;
  char Trail,buffer[2048]={0},check[1024]={0};
  
  while(1)
  {
    Socket->ReceiveBuf((char *)buffer,sizeof(fBuf));
    memmove((char *)&fBuf,(char *)buffer,sizeof(fBuf));        if(fBuf.Leading != 0x03) return;
    
    Socket->ReceiveBuf((char *)buffer,fBuf.Length sizeof(CRC) sizeof(Trail));        Trail = buffer[fBuf.Length sizeof(CRC)];
    if(Trail != 0x02) return;        CRC = buffer[fBuf.Length];
    memcpy((char *)check,(char *)&fBuf,sizeof(fBuf));
    memcpy((char *)check sizeof(fBuf),(char *)buffer,fBuf.Length);
    ckCRC = CRC_Compute((char *)check,sizeof(fBuf) fBuf.Length);
    
    其它處理
}
mieng
中階會員


發表:12
回覆:97
積分:81
註冊:2003-10-31

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-11-24 12:00:41 IP:61.60.xxx.xxx 未訂閱
嗯~~請問您body的大小,最大是多少呢?? 可以試試在傳送一個完整的header body 後,加上 Sleep(10); 試試,說不定就不會有被分成兩半的問題了~~ 學習中請大家多多指導呦~~ ☆星霧☆(Mineg Chien WU)
kenbcb
中階會員


發表:171
回覆:129
積分:60
註冊:2003-07-15

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-11-24 13:06:12 IP:61.222.xxx.xxx 未訂閱
我是接收的, 傳送我無法控制
pental
初階會員


發表:3
回覆:48
積分:30
註冊:2003-09-21

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-11-24 17:47:54 IP:203.74.xxx.xxx 未訂閱
當你開始在收 body 的時候,你可以知道你收到的大小是不是一個完整的 body或是只有一部份,如果只有一部份的話,那你就先把 body 暫存起來,等到下一次觸發 SocketRead 的時候,那你就把剩下的部分收進來就可以了,沒有時間寫範例給你,見諒囉!
kenbcb
中階會員


發表:171
回覆:129
積分:60
註冊:2003-07-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-11-25 09:28:22 IP:61.222.xxx.xxx 未訂閱
請問要如何偵測呢~可以提示嗎
pental
初階會員


發表:3
回覆:48
積分:30
註冊:2003-09-21

發送簡訊給我
#11 引用回覆 回覆 發表時間:2003-11-25 11:57:25 IP:203.74.xxx.xxx 未訂閱
void __fastcall TForm1::ClientSocket1Connect(TObject *Sender,
      TCustomWinSocket *Socket)
{
  int size = Socket->ReceiveBuf(Buffer,100000);          //每次嘗試讀取 100000 bytes 的資料    讀取完之後會得到實際讀取的 bytes 數      for(int i=0;i    以上是我寫的一個簡單的例子,並不是非常的完整,也沒有經過編譯測試,但是表達了我跟你提到的想法,在例子裡面我有用到 HeadStack 和 BodyStack 這是是一個類似 Stack 的 Class,只是 Pop 的時候,是會把 Stack 裡面所有的資料都 Pop 出來,另外 Buffer 是一個 char 陣列長度為 100000。你參考一下!     
        
kenbcb
中階會員


發表:171
回覆:129
積分:60
註冊:2003-07-15

發送簡訊給我
#12 引用回覆 回覆 發表時間:2003-11-26 09:10:35 IP:61.222.xxx.xxx 未訂閱
謝謝~我終於用出來了~ 感謝你的指導~
Eminem
一般會員


發表:0
回覆:4
積分:0
註冊:2004-12-03

發送簡訊給我
#13 引用回覆 回覆 發表時間:2004-12-03 11:47:51 IP:210.5.xxx.xxx 未訂閱
哇,这样做程序的效率不是很低吗? 每次收到数据都要遍历一下。
系統時間:2024-05-06 3:53:35
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!