GVKun编程网logo

Delphi(Indy)TIdTCPClient的主题(delphi coinitialize)

23

在这里,我们将给大家分享关于Delphi(Indy)TIdTCPClient的主题的知识,让您更了解delphicoinitialize的本质,同时也会涉及到如何更有效地c#–TcpClient.Ge

在这里,我们将给大家分享关于Delphi(Indy)TIdTCPClient的主题的知识,让您更了解delphi coinitialize的本质,同时也会涉及到如何更有效地c# – TcpClient.GetStream().Read()vs. TcpClient.Client.Receive()、Delphi - Indy TIdThreadComponent 线程研究、Delphi IdTCPClient IdTCPServer 点对点传送文件、delphi idtcpclient和idtcpserver的心跳包的内容。

本文目录一览:

Delphi(Indy)TIdTCPClient的主题(delphi coinitialize)

Delphi(Indy)TIdTCPClient的主题(delphi coinitialize)

在互联网上,我看到通常会将“TIdTCPClient”置于自定义TThread后代中……为什么这样做?

有时我也会在这样的线程中看到服务器……为什么?

干杯,
阿德里安

解决方法

Indy使用阻塞I / O,最好在线程中处理,这是Indy整体设计的核心.阻止主UI线程会给用户留下这样的印象,即应用程序实际上并未冻结.有关更多信息,请查看 “Introduction to Indy”.

c# – TcpClient.GetStream().Read()vs. TcpClient.Client.Receive()

c# – TcpClient.GetStream().Read()vs. TcpClient.Client.Receive()

.NET允许两种非常类似的方式从网络“读取”(假设TCP连接):
1. TcpClient.GetStream().Read() 
2. TcpClient.Client.Receive()

通过查看NetworkStream源代码 – 它似乎是底层套接字的额外包装器,最终调用Socket方法.

问题:使用“间接”NetworkStream变体(#1)的好处是什么,而不是使用Socket实现提供的直接包装器?

谢谢,
鲍里斯.

解决方法

实际上,使用第一个选项(Tcpstream而不是Socket)有一个非常明显的好处.好处是当针对同一程序需要不同的底层实现时,流API更灵活.

例如,有时可能使用SSL并且有时可能不使用SSL的代码可以在SslStream和Tcpstream之间切换而不更改调用代码.这是使用普通Socket API更难完成的事情.

Delphi - Indy TIdThreadComponent 线程研究

Delphi - Indy TIdThreadComponent 线程研究

 

Indy IdThreadComponent 线程研究

 

前几天在开发数据实时解析功能模块的时候,发现解析数据量巨大,特别耗时,程序一跑起来界面假死。

为了优化用户体验,采用了Indy 自带的IdThreadComponent控件,完美的解决了此问题。

下面就IdThreadComponent一些关键属性和方法做如下记录:

 

1:IdThreadComponent属性

这里主要记录一下Active、Priority和StopMode属性。

Active:默认False,当需要令IdThreadComponent控件生效时,置为True;

Priority:为避免线程之间相互冲突,选择normal,让系统自带分配优先级;

StopMode:这里分为Terminate和Suspend两种,Terminate为强行终止,Suspend为延缓、等待终止。

分享图片

 

2:IdThreadComponent方法

TIdThreadComponent用的是观察者模式,所有这里的事件都是回调事件。

一般比较耗时的操作放在OnRun中执行。

事件执行顺序如下:

On Before Execute;

On Before Run;

On Run; 

On Stopped;

On After Run;

On After Execute;

分享图片

 

3:通过如下Demo进行说明

需要说明一下:

在线程里不可以直接操作界面上的控件,因为有时候控件被销毁了而线程还在运行,这时直接操作会抛AV异常,所以在TIdThreadComponent回调事件中,如果有使用到控件的,必须先做控件是否为空的判断。

界面如下:

分享图片

代码如下:

  1 unit uMain;
  2 
  3 interface
  4 
  5 uses
  6   Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,  7   Dialogs,RzButton,StdCtrls,RzEdit,IdBaseComponent,IdThreadComponent;
  8 
  9 type
 10   TMainFrm = class(TForm)
 11     IDTrd: TIdThreadComponent;
 12     mmMsg: TRzMemo;
 13     btnStart: TRzBitBtn;
 14     btnStop: TRzBitBtn;
 15     btnTerminal: TRzBitBtn;
 16     procedure btnStartClick(Sender: TObject);
 17     procedure IDTrdRun(Sender: TIdCustomThreadComponent);
 18     procedure IDTrdBeforeExecute(Sender: TIdCustomThreadComponent);
 19     procedure IDTrdAfterExecute(Sender: TIdCustomThreadComponent);
 20     procedure btnStopClick(Sender: TObject);
 21     procedure btnTerminalClick(Sender: TObject);
 22     procedure IDTrdAfterRun(Sender: TIdCustomThreadComponent);
 23     procedure IDTrdBeforeRun(Sender: TIdCustomThreadComponent);
 24     procedure IDTrdStopped(Sender: TIdCustomThreadComponent);
 25   private
 26     { Private declarations }
 27   public
 28     { Public declarations }
 29   end;
 30 
 31 var
 32   MainFrm: TMainFrm;
 33 
 34 implementation
 35 
 36 {$R *.dfm}
 37 
 38 procedure TMainFrm.btnStartClick(Sender: TObject);
 39 begin
 40   IDTrd.Active := True;
 41 end;
 42 
 43 procedure TMainFrm.IDTrdRun(Sender: TIdCustomThreadComponent);
 44 var
 45   I: Integer;
 46 begin
 47   for I := 1 to 100 do
 48   begin
 49     mmMsg.Lines.Add(IntToStr(I)); //模拟耗时操作
 50   end;
 51   //在线程里不可以直接操作界面控件,有时候控件被销毁了而线程还在运行,
 52   //此时就会报AV异常,
 53   //所以在TIdThreadComponent回调事件中有使用到控件的,必须添加控件是否为空判断
 54 end;
 55 
 56 procedure TMainFrm.IDTrdBeforeExecute(Sender: TIdCustomThreadComponent);
 57 begin
 58   if Assigned(mmMsg) then
 59   begin
 60     mmMsg.Lines.Add(Before Execute);
 61   end;
 62 end;
 63 
 64 procedure TMainFrm.IDTrdAfterExecute(Sender: TIdCustomThreadComponent);
 65 begin
 66   if Assigned(mmMsg) then
 67   begin
 68     mmMsg.Lines.Add(After Execute);
 69   end;
 70 end;
 71 
 72 procedure TMainFrm.btnStopClick(Sender: TObject);
 73 begin
 74   IDTrd.Stop;
 75 end;
 76 
 77 procedure TMainFrm.btnTerminalClick(Sender: TObject);
 78 begin
 79   IDTrd.Terminate;
 80 end;
 81 
 82 procedure TMainFrm.IDTrdAfterRun(Sender: TIdCustomThreadComponent);
 83 begin
 84   if Assigned(mmMsg) then
 85   begin
 86     mmMsg.Lines.Add(After Run);
 87   end;
 88 end;
 89 
 90 procedure TMainFrm.IDTrdBeforeRun(Sender: TIdCustomThreadComponent);
 91 begin
 92   if Assigned(mmMsg) then
 93   begin
 94     mmMsg.Lines.Add(Before Run);
 95   end;
 96 end;
 97 
 98 procedure TMainFrm.IDTrdStopped(Sender: TIdCustomThreadComponent);
 99 begin
100   if Assigned(mmMsg) then
101   begin
102     mmMsg.Lines.Add(On Stopped);
103   end;
104 end;
105 
106 end.

Delphi IdTCPClient IdTCPServer 点对点传送文件

Delphi IdTCPClient IdTCPServer 点对点传送文件

https://blog.csdn.net/luojianfeng/article/details/53959175

 

2016年12月31日 23:40:15
阅读数:2295

分享图片

Delphi     IdTCPClient 点对点传送文件


客户端向另一个客户端传送文件,不通过服务端中转
那一个很重要的点是,这个客户端也要放一个IdTcpserver,也就是说这个客户端既是客户端,当接收文件的时候也是服务端,必须相应其它客户


端对它的连接,这个时候客户端相当与服务端,好了,明白这个道理就好办了


A客户端(放一个IdTCPClient控件,发送文件)

 

procedure TFormFileSend.FormShow(Sender: TObject);//连接到服务端,同时自己变成服务端
begin

  //自己变成服务端
  IdTcpserver1.Bindings.Clear;
  IdTcpserver1.Bindings.Add.IP:=‘192.168.252.1‘;
  IdTcpserver1.Bindings.Add.Port:=8831;
  IdTcpserver1.Active:=true;
  if  IdTcpserver1.Active then
  begin
    Memo1.Lines.Add(‘服务器已启动‘);
  end
  else
  begin
    Memo1.Lines.Add(‘服务器已停止‘);
  end;

  //连接到服务端
  IdTCPClient1.Host:=FormMain.host;//‘192.168.252.1‘;
  IdTCPClient1.Port:=StrToInt(FormMain.port);//8829;
  if IdTCPClient1.Connected then
    IdTCPClient1.disconnect;
  Try
    IdTCPClient1.Connect;
    IdTCPClient1.WriteLn(FormMain.qm+‘|‘+FormMain.bh);
  except
    MessageBox(Handle,‘服务器没有开启‘,‘提示‘,MB_OK);
    Exit;
  end;


  loading();//连接到服务端,显示上线的客户端
end;


procedure TFormFileSend.loading();
var
  Node: TTreeNode;
begin
  RzCheckTree1.Items.Clear;


  sleep(500);//这里一定要延时,不然下面的数据明明有,但是读不出来, 2016-12-31
  
  with ADOQuery2 do
  begin
    sql.Clear;
    sql.Add(‘select a.ip,a.bh,a.qm,c.qm as bm from ipdz a left join zy b on a.bh=b.bh left join bm c on b.szbm=c.bh ‘);
    Open;
    while not Eof do
    begin
      Node := RzCheckTree1.Items.AddChild(nil,FieldByName(‘qm‘).Asstring+‘(‘+FieldByName(‘bm‘).Asstring+‘)‘+FieldByName(‘ip‘).Asstring);
      Node.Data:=strnew(PChar(FieldByName(‘ip‘).Asstring));
      Next;
    end;
  end;
end;



procedure TFormFileSend.SpeedButton1Click(Sender: TObject);//发送文件
var
  iFileHandle:integer;
  iFileLen,cnt:integer;
  buf:array[0..4096] of byte;


  i: integer;
  zt:Boolean;
begin
  if Edit1.Text=‘‘ then
  begin
    ShowMessage(‘请选择要上传的文件‘);
    Exit;
  end;


  zt:=False;
  for i:=0 to RzCheckTree1.Items.Count - 1 do
  begin
    if RzCheckTree1.ItemState[i] = cschecked then
    begin
      zt:=True;
    end;
  end;
  if zt=False then
  begin
    Application.MessageBox(‘请选择接收人!‘,64);
    exit;
  end;


  for i:=0 to RzCheckTree1.Items.Count - 1 do
  begin
    if RzCheckTree1.ItemState[i] = cschecked then
    begin
      IdTCPClient2.Host:=PChar(RzCheckTree1.Items.Item[i].Data);
      IdTCPClient2.Port:=8831;
      if IdTCPClient2.Connected then
        IdTCPClient2.disconnect;
      Try
        IdTCPClient2.Connect;
      except
        Memo1.Lines.Add(RzCheckTree1.Items.Item[i].Text+‘不在线‘);
        continue;
      end;


      iFileHandle:=FileOpen(Edit1.Text,fmOpenRead);
      iFileLen:=FileSeek(iFileHandle,2);
      FileSeek(iFileHandle,0);
      ProgressBar1.Max:=iFileLen;
      ProgressBar1.Position := 0;
      IdTCPClient2.WriteLn(ExtractFileName(Edit1.Text)+‘|‘+IntToStr(iFileLen));
      while true do
      begin
        Application.ProcessMessages;
        cnt:=FileRead(iFileHandle,buf,4096);
        IdTCPClient2.WriteBuffer(buf,cnt);
        ProgressBar1.Position:=ProgressBar1.Position + cnt;
        Memo1.Lines.Add(‘正在传送文件...‘+DateTimetoStr(Now));
        if cnt<4096 then
          break;
      end;
      FileClose(iFileHandle);
      Memo1.Lines.Add(‘文件传送完成!‘+DateTimetoStr(Now));
    end;
  end;

end;

 

procedure TFormFileSend.SpeedButton5Click(Sender: TObject);//取消发送var  i:Integer;begin  FileClose(iFileHandle);  IdTCPClient2.disconnect;  for i:=0 to RzCheckTree1.Items.Count - 1 do  begin    if RzCheckTree1.ItemState[i] = cschecked then    begin      IdTCPClient2.Host:=PChar(RzCheckTree1.Items.Item[i].Data);      IdTCPClient2.Port:=8831;      if IdTCPClient2.Connected then        IdTCPClient2.disconnect;      Try        IdTCPClient2.Connect;      except        Memo1.Lines.Add(RzCheckTree1.Items.Item[i].Text+‘不在线‘);        continue;      end;      IdTCPClient2.WriteLn(‘取消发送‘);      IdTCPClient2.disconnect;    end;  end;  //Sleep(500);  Memo1.Lines.Add(‘取消文件发送‘+DateTimetoStr(Now));end;

B客户端(要放一个IdTcpserver控件,相当于服务端接收) procedure TFormFileSend.IdTcpserver1Execute(AThread: TIdPeerThread); var   rbyte:array[0..4096] of byte;   sFile:TFileStream;   cmd,FileSize:integer;   str,FileName:string; begin   if not AThread.Terminated and AThread.Connection.Connected then  //注意这里   begin     with AThread.Connection do     begin       Try         str:=AThread.Connection.ReadLn;         if POS(‘|‘,str)>0 then         begin           cmd:=pos(‘|‘,str); //查找分隔符           FileName:=copy(str,1,cmd-1); //提取文件名           FileSize:=StrToInt(copy(str,cmd+1,Length(str)-cmd+1)); //提取文件大小           if MessageBox(0,Pchar(‘您有文件 "‘+FileName+‘" 您是接受还是拒绝?‘),‘文件接受‘,MB_YesNo or MB_ICONQUESTION)=ID_Yes  then //询问是否接收           begin               ProgressBar1.Max:=FileSize div 100;   //初始化进度条               ProgressBar1.Position:=0;               SaveDialog1.FileName:=FileName; //指定保存的默认文件名,一定要在 SaveDialog1.Execute;之前,不然文件名为空               SaveDialog1.Execute;               sFile:=TFileStream.Create(SaveDialog1.FileName,fmCreate); //创建待写入的文件流               While FileSize>4096 do               begin                 Application.ProcessMessages;                 AThread.Connection.ReadBuffer(rbyte,4096);// 读取文件流                 ProgressBar1.Position:=ProgressBar1.Position + (4096 div 100); //更新显示进度                 Memo1.Lines.Add(‘正在接收文件中...‘+DateTimetoStr(Now));                 sFile.Write(rByte,4096);      //写入文件流                 inc(FileSize,-4096);               end;               AThread.Connection.ReadBuffer(rbyte,FileSize);// .ReadBuffer(rbyte,iLen);               sFile.Write(rByte,FileSize);               sFile.Free;               Memo1.Lines.Add(‘文件接收完成!‘+DateTimetoStr(Now));           end;         end;       Finally         //disconnect;//断开连接       end;     end;   end;       end;

delphi idtcpclient和idtcpserver的心跳包

delphi idtcpclient和idtcpserver的心跳包

总结

以上是小编为你收集整理的delphi idtcpclient和idtcpserver的心跳包全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

今天关于Delphi(Indy)TIdTCPClient的主题delphi coinitialize的介绍到此结束,谢谢您的阅读,有关c# – TcpClient.GetStream().Read()vs. TcpClient.Client.Receive()、Delphi - Indy TIdThreadComponent 线程研究、Delphi IdTCPClient IdTCPServer 点对点传送文件、delphi idtcpclient和idtcpserver的心跳包等更多相关知识的信息可以在本站进行查询。

本文标签: