IdTcpServer/IdTcpClient
IdTcpServer
uses IdContext //需要引用
属性,方法:
IdTCPServer.Active :=True; //开启服务器
IdTCPServer1.Bindings.Add.IP := '127.0.0.1';//绑定 IP
IdTCPServer1.Bindings.Add.Port := 7956;//绑定端口
事件:
OnConnect : 客户端连接成功触发
OnDisConnect : 客户端断开触发
OnExeCute : 收到客户端数据触发
例子
//像所有客户断发送数据
var
I: Integer;
Context: TIdContext;
begin
with IdTCPServer1.Contexts.LockList do
try
for I := 0 to Count - 1 do
begin
Context := TIdContext(Items[I]);
Context.Connection.IOHandler.Write('Hello,everybod
y!');
end;
finally
IdTCPServer1.Contexts.UnlockList;
end;
end;
//向某个客户发送数据
var
I: Integer;
Context: TIdContext;
begin
with IdTCPServer1.Contexts.LockList do
try
for I := 0 to Count - 1 do
begin
Context := TIdContext(Items[I]);
if Context.Binding.PeerIP <> '192.168.10.90' then
continue;
Context.Connection.IOHandler.Write('Hello!');
end;
finally
IdTCPServer1.Contexts.UnlockList;
end;
end;
IdTcpClient
属性,方法:
ConnectTimeOut:连接超时
Host:主机 IP 或域名
IPVersion:Ip 版本 ipv4 or ipv6
Name:控件名
Port:主机端口
ReadTimeOut:读取超时
IdTCPClient1.Connect; //连接服务端
IdTCPClient1.Disconnect;//端开连接
IdTCPClient1.Connected;//是否连接成功 返回 true 连接成功
IdTCPClient1.IOHandler.WriteLn('aa');// 向服务端发送数据
OnWork 事件 AWorkMode=wmRead
表示有收到数据
在 DelPhi2007 中 使用 Indy 的 TCP 连接教程
(一)
首先 先说明下 为什么要用 INDY10
最新的 indy10 可以基于 win32 上的程(Fiber) API.
什么叫 Fiber API 呢,这里是解释:
纤程(Fiber) — 可以从 32 位版本的 Windows? 中使用的轻量级线程
处理对象 — 在很多方案中都很有用。由于线程是宝贵资源,因此您有时不希望
将整个 OS 线程专门用于执行简单的任务。通过纤程,可以比线程更严密地控制
任务的调度,因为是您而不是 OS 负责管理它们。由于它们具有较少的开销,因
此当您切换上下文时,它们还更加快速。此外,因为是由您控制纤程,所以对于
它们而言,通常可以更容易地跟踪同步问题。
不过这个特性,现在只有针
对 delphi7 有用。
端口重叠可以让你的服务器承担更多的用户。indy10 值得一用。
indy10 支持完成端口和纤程,性能有了巨大提升!
=====================================================================
===========
我们先打开
DelPhi2007 工具吧!
首先 我们 做好一个简单的客户端
先新建一个窗口程序 拖入一个 TCP 客户端控件 还有 3 个按钮 一个文本框 是
连接 断开 和 发生
设置一下 IdTCPClient 控件的属性
Host :127.0.0.1
Post:3000
下面 我们来对连接按钮做事件
procedure TForm6.ConetClick(Sender: TObject);
begin
try
if not (IdTCPClient1.Connected) then
IdTCPClient1.Connect;
ShowMessage('连接成功');
except
ShowMessage('连接失败');
end;
end;
接着 我们来做一下服务端的程序
先新建一个窗口程序 拖入一个 TCP 服务端控件 两个按钮 以及一个 TMemo 用来
显示信息
Bindings 0.0.0.0:3000
DefaultPort 3000
我们在“启动服务” 按钮上 的事件
procedure TForm6.Button1Click(Sender: TObject);
begin
IdTCPServer1.Active:= true;
end;
启动时 只要将其 Active 设置为 true 既启动了服务 而关闭则同样设置为
False
接下来 我们要对 IdTCPServer1 的 OnExecute 事件做处理! 选择控件 EVENTS
栏双击 OnExecute
在这里 代码我们暂时这样写
procedure TForm6.IdTCPServer1Execute(AContext: TIdContext);
begin
exit;
end;
TIdContext 需要 uses IdContext
好 到这里 运行下服务器 和 客户端 然后 启动服务器 和 连接服务器
好 已经可以连接得上了吧!
但是 因为 我们在服务器监听的部分退出了 所以 并没有保持着连接
现在 我们 修改一下 代码吧 我们把 OnExecute 代码修改如下
procedure TForm6.IdTCPServer1Execute(AContext: TIdContext);
var
Swp:String;
begin
try
AContext.Connection.IOHandler.CheckForDisconnect(True, True);
Swp:=AContext.Connection.IOHandler.ReadLn();
Memo1.Lines.Add(Swp) ;
finally
end;
end;
我们对客户端也修改一下
procedure TForm6.ConetClick(Sender: TObject);
begin
try
if not (IdTCPClient1.Connected) then
begin
IdTCPClient1.Connect;
IdTCPClient1.IOHandler.writeln('lianjie');
ShowMessage('连接成功');
end;
except
ShowMessage('连接失败');
end;
end;
在运行测试一下
当按下连接按钮后 服务器上的文本框里 加入了一行 'lianjie' 字符串而其再
次点击连接已经无效 而刚刚每次点击一次 都会提示一次连接成功 仔细看代码
就发现 在连接的时候判断了是否已经连接了如果已经保持连接了哪么就不会在
做下面的代码!从而可知现在的连接已经是保持着的了! 那好我们来发个信息
看下是否真的可以连接了
在发送按钮上的事件
procedure TForm6.SendClick(Sender: TObject);
var
Str:String;
begin
Str:=Edit1.Text;
if(IdTCPClient1.Connected) then
IdTCPClient1.IOHandler.writeln(Str);
end;
好 我们来测试一下 是不是连接以后真的可以向服务器发送数据了呢?
看到了吧! 是不是可以发送数据了!
在 Delphi
2007 中使用 Indy10 的 TCP 连接的教程(系
列二)
服务器怎么样区别数据到底是哪一个发送过来的呢,或者服务器如何对其回复数
据呢!~
先针对回复对应的客户端发送过来的数据!已经客户端接受并显示服务器反馈回
来的数据!
我们修改服务器上的 OnExecute 代码如下!
procedure TForm6.IdTCPServer1Execute(AContext: TIdContext);
var
Swp:String;
begin
try
AContext.Connection.IOHandler.CheckForDisconnect(True, True);
Swp:=AContext.Connection.IOHandler.ReadLn();
if(Swp<>'')then
AContext.Connection.IOHandler.WriteLn('服务器已经收到您发来的信息:
'+Swp);
Memo1.Lines.Add(Swp) ;
finally
end;
end;
在客户端里我们加入一个 TMemo 用来接受服务器发来的数据信息!
然后我们在来看客户端的代码!
在连接和发送按钮上的事件修改为
procedure TForm6.ConetClick(Sender: TObject);
begin
try
if not (IdTCPClient1.Connected) then
begin
IdTCPClient1.Connect;
IdTCPClient1.IOHandler.writeln('lianjie');
Str:=IdTCPClient1.IOHandler.ReadLn();
Memo1.Lines.Add(Str);
ShowMessage('连接成功');
end;
except
ShowMessage('连接失败');
end;
end;
procedure TForm6.SendClick(Sender: TObject);
var
Str:String;
begin
Str:=Edit1.Text;
if(IdTCPClient1.Connected) then
IdTCPClient1.IOHandler.writeln(Str);
try
Str:=IdTCPClient1.IOHandler.ReadLn();
Memo1.Lines.Add(Str);
finally
end;
end;
我们编译后 打开多个客户端进行测试 就会发现 对不同客户端服务器会分别的
响应并对其回复内容 互不干扰!
做到这里 大家也知道客户端如果要发送一条数据才能相应的去读取一条数据!
可能有些人会想到利用定时器对数据进行定时读取!~ 这样也是一个办法!但是
在程序操作中 由于数据太快而没有及时读取就会出现数据丢失掉了!那我们要
用什么方法才能很好的对数据进行准确读取呢!在这里我使用了线程!启用一个
线程利用一个死循环对数据进行读取!一旦有数据就读取出来并放在一个
StringList 里 供我们使用!
好我们一步步的来实现!
我们先来做一全局变量的定义 新建一全局变量页面 MainUnit.pas
我们先声明两个全局变量
代码如下
unit MainUnit;
interface
uses Classes,SyncObjs;
var
M_Lock : TCriticalSection;//临界区,多线程同步问题。TCriticalSection
M_MsgList:TStringList;
implementation
end.
然后我们在主程序的窗口创建事件里创建这两个对象
procedure TForm6.FormCreate(Sender: TObject);
begin
M_MsgList:=TStringList.Create;
M_Lock
end;
:=TCriticalSection.Create;
接下来我们把这个页面引用到程序中 以及线程代码中 线程页面 MyThread.pas
代码如下
unit MyThread;
interface
uses Classes,SysUtils,Forms,Windows,Variants,idIOHandler,MainUnit;
type
TMainThread = class(TThread)
private
protected
procedure Foo;
procedure Execute;Override;
public
Constructor Create(Suspended:Boolean);
end;
implementation
uses Client;
Constructor TMainThread.Create(Suspended:Boolean);//创建线程
Begin
inherited Create(Suspended);
FreeOnTerminate:=True;
End;
procedure TMainThread.Foo;
var
Msg:string;
bool: boolean;
begin
bool:=true;
while bool do begin
try
Msg:= Form6.IdTCPClient1.IOHandler.ReadLn;
if(Msg='') then