点对点的TCP通信 只能俩个人 用了UDP广播发送服务器的IP和端口号 然后客户端获取其IP和端口
unit kehu;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient, FMX.StdCtrls, FMX.Edit,
FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, IdTCPConnection,
IdTCPClient,IdGlobal, IdUDPServer, IdSocketHandle;
type
TKeHu_Form = class(TForm)
jieshou: TMemo;
fasong: TEdit;
bt: TButton;
IdTCPClient1: TIdTCPClient;
IdUDPServer1: TIdUDPServer;
procedure FormShow(Sender: TObject);
procedure TCP_js;
procedure btClick(Sender: TObject);
procedure IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
private
{ Private declarations }
public
{ Public declarations }
end;
var
KeHu_Form: TKeHu_Form;
implementation
{$R *.fmx}
procedure TKeHu_Form.btClick(Sender: TObject);
var
len : Integer;
buf : array [0..100] of char;
msg : TIdBytes;
begin
if not IdTCPClient1.Connected then
begin
if IdTCPClient1.Port = 0 then
begin
ShowMessage('还没有连接上哟!再等待一会儿');
end;
end
//连接上了 发消息 msg
else
begin
//长度是两倍 可以发汉字 p
len := Length(fasong.Text)*2;
msg := RawToBytes(len,SizeOf(len));
strcopy(buf, Pchar( fasong.Text));
msg := msg+ RawToBytes(buf,len);
IdTCPClient1.IOHandler.Write(msg,SizeOf(len)+len);
fasong.Text := '';
jieshou.Text := jieshou.Text + '我:'+ buf + #13#10;
end;
end;
procedure TKeHu_Form.FormShow(Sender: TObject);
begin
//tcp
IdTCPClient1.Port := 0;
//udp
IdUDPServer1.DefaultPort := 11112;
IdUDPServer1.Active := true;
end;
procedure TKeHu_Form.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
begin
IdTCPClient1.Host := ABinding.PeerIP;
IdTCPClient1.Port := StrToInt(BytesToString(AData));
//接受到了 就 连接 TCP
IdTCPClient1.Connect;
TThread.CreateAnonymousThread(TCP_js).start;
//关闭接受 不这样会卡死 false
TThread.CreateAnonymousThread(
procedure
begin
IdUDPServer1.Active := false;
end
).Start;
end;
//TCP js msg
procedure TKeHu_Form.TCP_js;
var
buf : array [0..100] of char;
len : Integer;
msg : TIdBytes;
begin
while True do
begin
//清空数组
//这个线程一直运行 不是像控件的事件一样 新开线程
//所以buf用过之后需要清空 以防 读取上一次的残留数据
fillchar(buf, sizeof(buf), 0);
//先读取包的长度 len
IdTCPClient1.IOHandler.ReadBytes(msg,SizeOf(len));
BytesToRaw(msg,len,SizeOf(len));
//读取包中的数据 msg
msg := nil;
IdTCPClient1.IOHandler.ReadBytes(msg,len);
//字节转到 buf
BytesToRaw(msg,buf,len);
jieshou.Text :=jieshou.Text +'服务器:' + buf + #13#10;
msg := nil;
end;
end;
end.
unit fuwu;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer, FMX.StdCtrls, FMX.Edit,
FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, IdCustomTCPServer,
IdTCPServer, IdContext,IdGlobal, IdIPWatch, IdUDPClient;
type
TFuWu_form = class(TForm)
jieshou: TMemo;
fasong: TEdit;
bt: TButton;
IdTCPServer1: TIdTCPServer;
IdIPWatch1: TIdIPWatch;
IdUDPClient1: TIdUDPClient;
procedure FormShow(Sender: TObject);
procedure fs;
procedure IdTCPServer1Execute(AContext: TIdContext);
procedure btClick(Sender: TObject);
private
{ Private declarations }
kehu : TIdContext;
public
{ Public declarations }
end;
var
FuWu_form: TFuWu_form;
implementation
{$R *.fmx}
procedure TFuWu_form.btClick(Sender: TObject);
var
len : Integer;
buf : array [0..100] of char;
msg : TIdBytes;
begin
if kehu = nil then
begin
ShowMessage('无人连接');
end
else
begin
//长度是两倍 可以发汉字 p
len := Length(fasong.Text)*2;
msg := RawToBytes(len,SizeOf(len));
strcopy(buf, Pchar( fasong.Text));
msg := msg+ RawToBytes(buf,len);
kehu.Connection.IOHandler.Write(msg,SizeOf(len)+len);
fasong.Text := '';
jieshou.Text := jieshou.Text + '我:'+ buf + #13#10;
end;
end;
procedure TFuWu_form.FormShow(Sender: TObject);
begin
//设置 UDPserver
IdUDPClient1.BoundIP := IdIPWatch1.LocalIP;
//记得开广播使能 要不然无法发送 广播 true
IdUDPClient1.BroadcastEnabled := true;
IdUDPClient1.Active := true;
TThread.CreateAnonymousThread(fs).Start;
//设置TCPserver
IdTCPServer1.DefaultPort := 11111;
IdTCPServer1.Active := true;
//连接
kehu := nil;
end;
//一直不停的发送广播 fs
procedure TFuWu_form.fs;
begin
while True do
begin
//发送 ip and port
IdUDPClient1.Send('255.255.255.255',11112,'11111');
TThread.Sleep(2000);
//如果连接上了就不需要广播了
if Assigned(kehu) then
begin
break;
end;
end;
end;
procedure TFuWu_form.IdTCPServer1Execute(AContext: TIdContext);
var
buf : array [0..100] of char;
len : Integer;
msg : TIdBytes;
begin
//数组的初始值是确定的 里面的值不规律 先清零
//否则接收到数据 后面的值不为#0 则会多输出一些符号
fillchar(buf, sizeof(buf), 0);
kehu := AContext;
//先读取包的长度 len
AContext.Connection.IOHandler.ReadBytes(msg,SizeOf(len));
BytesToRaw(msg,len,SizeOf(len));
//读取包中的数据 msg
msg := nil;
AContext.Connection.IOHandler.ReadBytes(msg,len);
//字节转到 buf
BytesToRaw(msg,buf,len);
jieshou.Text :=jieshou.Text +'客户端:' + buf + #13#10;
end;
end.
总结
1.发广播的时候广播使能要开
2.发送一般用client 接收一般用server 方便