一、Server端
使用的indy控件:
idtcpsrvr1: TIdTCPServer; a)设置默认端口
begin
Self.btn1.Enabled:=False;
idtcpsrvr1.DefaultPort:=2001;
idtcpsrvr1.Active:=True;
end; b)对客户端连接事件响应
procedure TForm1.idtcpsrvr1Connect(AThread: TIdPeerThread);
var
ipStr:string;
begin
ipStr:=AThread.Connection.Socket.Binding.PeerIP;
ShowMessage('IP地址为: '+ipStr+' 的用户连接过来!');
end;c)对客户端发送过来的字符串进行显示,并通知客户端接收成功
procedure TForm1.idtcpsrvr1Execute(AThread: TIdPeerThread);
var
str:string;
begin
with AThread.Connection do
begin
str:=readln('',5000);
inc(messageId);
WriteLn('第'+inttostr(messageId)+'条数据接收成功,内容为:'+str);
end;
end;
二、Client端
Socket:TIdTCPClient;a)指定Server端ip和端口号begin
Socket := TIdTCPClient.Create(nil);
Socket.Host:='127.0.0.1';
Socket.Port:=2001;
end;b)建立连接if not socket.Connected then
begin
try
socket.Connect(5000);
Memo1.Lines.Add('socke连接已经成功建立!');
btn1.Caption:='断开连接';
except
ShowMessage('连接失败,请检查连接设置!');
end;
end
注:socket连接建立失败的两种情形:
1)探测找不到目标主机:此时会等到timeout时间结束后,抛出连接异常
2)探测到目标主机,但是目标主机上socket连接未开:立即抛出连接异常
c)发送与接收数据
var
RequestStr,BackStr:string;
begin
if socket.Connected then
begin
RequestStr:='tttttttttttt';
try
socket.WriteLn(RequestStr);
Memo1.Lines.Add('发送数据:'+RequestStr);
BackStr:=socket.ReadLn('',5000); //实际上timeout是不起作用的,indy本身
//的bug;此时如果server端无数据则会死等
Memo1.Lines.Add('返回数据:'+BackStr);
except
ShowMessage('发送数据失败!');
end;
end
else
begin
Memo1.Lines.Add('连接已被断开,无法发送!');
end;
end;
说明:1)indy的TIdTCPClient是阻塞式的,程序会停在那里等待接收,故有以下两种读取数据的方式:
a)可以单独启一个线程来负责接收
b)通过timer来监控是否有新数据到
procedure timer.ontimer.................
var temp:string;
begin
idtcpclient.readfromstack(false,1,false);
while idtcpclient.InputBuffer.Size> 0 do begin
temp:=idtcpclient.ReadLn;
end;
end; 2)如果能知道要取的数据包的大小,可以用readbuffer(abuffer,包长度)来取得包。
d)断开连接
begin
try
socket.Disconnect;
Memo1.Lines.Add('socket连接已断开!');
btn1.Caption:='建立连接';
except
ShowMessage('断开连接时出错!');
end;
end;
本文介绍了如何在Delphi中利用Indy控件进行TCP Socket通信,包括Server端和Client端的设置。在Client端,提到了连接失败的两种情况:目标主机未找到及目标主机的socket未开启。在数据交互方面,提到了TIdTCPClient的阻塞特性,建议通过单独线程或Timer监控数据接收,并讨论了断开连接的操作。
2066

被折叠的 条评论
为什么被折叠?



