天天看點

Delphi TIdTCPClient的使用問題

開發環境Delphi10.3.3

使用TIdTCPClient寫了一個用戶端小例子,使用網絡調試助手作為服務端(設定接收到用戶端資訊會自動傳回資料)。

通訊模式:短連接配接。用戶端連接配接--發送---等待資料---接收---斷開。此例子中用戶端不知道傳回資訊長度是多少。

問題:由于不确定服務端傳回資料多少,是以使用Socket.ReadBytes(dat,-1,False); -1:表示一直讀取直到逾時。本以為像ClientSocket那樣有多少資料就能讀到多少,結果試驗了不同長度的資料,讀取到的長度也不一樣。1000多個位元組沒問題,超過2920就會出現讀取不夠的情況(經常在2920出問題,但也不全是)。讀取結束後disconnect,再次connect就會抛出Already connected異常。

如果Socket.ReadBytes(dat,-1,False);  第二個參數設定為正數,表示要讀取的位元組數,如果實際傳回的小于參數則會一直等待到readtimeout,然後抛出逾時異常。如果大于參則讀取成功。但這兩種情況都是導緻再次connect抛出Already connected異常。

解決Already connected異常的辦法是idtcpclnt1.Socket.InputBuffer.Clear;

解決讀取資料不夠的辦法是循環調用Socket.ReadBytes(dat,-1,False); 

改進後如下:

procedure TReadThread.Execute;
var
  dat:TIdBytes;
  msg:AnsiString;
  count:Integer;
  tcpclient:TIdTCPClient;
begin
  FreeOnTerminate:=true;
  try
    tcpclient:=TIdTCPClient.Create();
    with tcpclient do
    begin
      Host := Form1.edtIP.Text;
      Port := StrToInt(Form1.edtPort.Text);
      Connect;
      Form1.mmo1.Lines.Add('connected') ;
      Socket.Write('阿斯蒂芬',IndyTextEncoding_OSDefault);

      Form1.mmo1.Lines.Add('等待接收') ;
      Socket.ReadTimeout:=1000*6;//讀取逾時時間

      if Socket.CheckForDataOnSource(1000*60) then//等待資料60秒,有資料傳回true
      begin
        repeat
          SetLength(dat, 0); 
          Socket.ReadBytes(dat,-1,False);
          count:=count+Length(dat);
          msg:=BytesToString(dat,IndyTextEncoding_OSDefault);

          Form1.mmo1.Lines.Add('資料長度:'+IntToStr(Length(dat))) ;
        until (Socket.CheckForDataOnSource(500)=False);

        Form1.mmo1.Lines.Add('總長度:'+IntToStr(count)) ;
      end
      else
      begin
        if Connected then
          Form1.mmo1.Lines.Add('等待逾時')
        else
          Form1.mmo1.Lines.Add('已斷開連接配接') ;
      end;
      //關閉
      if connected then
      begin
        if Socket.InputBufferIsEmpty then
          Form1.mmo1.Lines.Add('true')
        else
          Form1.mmo1.Lines.Add('false');
        Socket.InputBuffer.Clear;
        DisConnect;
      end;
    end;
  except
  on E : Exception do
    begin
      Form1.mmo1.Lines.Add('異常:'+E.Message+'['+e.ClassName+']');
    end;
  end;
end;
           
上一篇: 關于object類
下一篇: 測試的流程

繼續閱讀