Indy TIdTCPClient伪非阻塞式的解决方案

Indy是阻塞式Socekt,通过线程的方式,我们可以避免程序被阻塞。

平时在开发中,是直接用的同步模式,在线程中进行一问,一答的交互。但是这就遇到了一个问题,就是服务器没有立马响应,我们的程序就出现readtimeout异常。



这个时候就采用异步阻塞模式。

发送和接受不再是成对的了。

首先连接是服务器:

procedure TForm1.btnloginClick(Sender: TObject);
begin
  tmrRecive.Enabled := True;//定时器启动
  idtcpclnt1.Host := 'xx.xx.xx.xx';
  idtcpclnt1.Port := 888;
  idtcpclnt1.ConnectTimeout := 10000;
  try
    idtcpclnt1.Connect;
  except On E:Exception do
    begin
      ShowMessage('连接报错' + e.Message);
      Exit;
    end;
  end;
end;

发送数据

procedure TForm1.btnSendClick(Sender: TObject);
const
  data: array[0..32] of Byte = (23, 32, 3, 1, 23, 25, 0, 8, 0, 86, 49, 46, 48, 46, 48, 46, 48, 4, 0, 57, 48, 50, 53, 5, 0, 77, 65, 67, 80, 67, 1, 12, 15);
var
  ReqBuf, RespBuf: TIdBytes;
  I: Integer;
begin
  SetLength(ReqBuf, 33);
  for I := 0 to Length(ReqBuf) - 1 do
  begin
   ReqBuf[I] := data[I];
  end;

  try
    idtcpclnt1.IOHandler.Write(ReqBuf);
  except
    on e: Exception do
    begin
      ShowMessage('发送' + e.Message);
      Exit;
    end;
  end;
end;


定时器轮询接收

procedure TForm1.tmrReciveTimer(Sender: TObject);
var
  RespBuf: TIdBytes;
begin
  if (idtcpclnt1.Connected) and (not idtcpclnt1.Socket.InputBufferIsEmpty) then
  begin
    try
      { fill the output buffer with a timeout of 10 ms }
      idtcpclnt1.IOHandler.CheckForDataOnSource(10);
      idtcpclnt1.IOHandler.InputBuffer.ExtractToBytes(RespBuf, -1, False, -1);
    except
       on e: Exception do
       begin
         ShowMessage('接收' + e.Message);
         Exit;
       end;
    end;
  end;
end;




版权声明:本文为QustDong原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。