Delphi UPD通讯演示

服务端:

1.  定义结构

type
  TMyRecord = record
    Ip: array[0..16] of Char;
    Port: Integer;
    Data: array[0..1023] of Char;
  end;

2. 窗体创建的时候设置IP,端口

procedure TfrmServer.FormCreate(Sender: TObject);
begin
  idpsrvr1.Bindings.Add;
  idpsrvr1.Bindings[0].IP := GetLocalIP;
  idpsrvr1.Bindings[0].Port := 8098;
  idpsrvr1.Active := True;
  Caption := Format('Server: [%s:%d]', [idpsrvr1.Bindings[0].IP,
    idpsrvr1.Bindings[0].Port]);
  mmo1.DoubleBuffered := True;
end;

3. 设置TIdUDPServer的OnRead事件。

procedure TfrmServer.idpsrvr1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  ReceiveData: TMyRecord;
  SendData: TMyRecord;
begin
  ZeroMemory(@ReceiveData, SizeOf(ReceiveData));
  ZeroMemory(@SendData, SizeOf(SendData));
  AData.Read(ReceiveData, SizeOf(ReceiveData));
  StrPLCopy(SendData.Ip, idpsrvr1.Bindings[0].IP, Length(SendData.Ip));
  SendData.Port := idpsrvr1.Bindings[0].Port;
  StrLCopy(SendData.Data, ReceiveData.Data, Length(SendData.Data));
  AddData(Format('IP: %s Port: %d  Data: %s',
    [ReceiveData.Ip, ReceiveData.Port, ReceiveData.Data]));
  idpsrvr1.SendBuffer(ReceiveData.Ip, ReceiveData.Port, ReceiveData,
    SizeOf(ReceiveData));
end;

获取本机IP地址函数

function GetLocalIP: string; //获取本机局域网IP
type
  TaPInAddr = array[0..10] of PInAddr;
  PaPInAddr = ^TaPInAddr;
var
  phe: PHostEnt;
  pptr: PaPInAddr;
  Buffer: array[0..63] of char;
  I: Integer;
  GInitData: TWSADATA;
begin
  Result := '';
  WSAStartup($101, GInitData);
  try
    GetHostName(Buffer, SizeOf(Buffer));
    phe := GetHostByName(Buffer);
    if nil <> phe then
    begin
      pptr := PaPInAddr(Phe^.h_addr_list);
      I := 0;
      while nil <> pptr^[I] do
      begin
        Result := StrPas(inet_ntoa(pptr^[I]^));
        Inc(I);
      end;
    end;
  finally
    WSACleanup;
  end;
end;

 

客户端:

1. 绑定IP

procedure TfrmClient.btnIpClick(Sender: TObject);
begin

    idpsrvr1.Bindings.Add;
    idpsrvr1.Bindings[0].IP := GetLocalIP;
    idpsrvr1.Bindings[0].Port := StrToInt(cbb1.Text);

    idpsrvr1.Active := True;
    ShowMessage('OK');
end;

 

2. 发送数据

procedure TfrmClient.btnSendClick(Sender: TObject);
var
  MyRecord: TMyRecord;
  DataStr: string;
begin
  //自己的IP地址
  StrPLCopy(MyRecord.Ip, idpsrvr1.Bindings[0].IP, Length(MyRecord.Ip));
  //自己的端口
  MyRecord.Port := idpsrvr1.Bindings[0].Port;
  DataStr := 'Client: ' + edtMsg.Text;
  StrPLCopy(MyRecord.Data, DataStr, Length(DataStr));
  idpsrvr1.SendBuffer(FServerIp, FServerPort, MyRecord, SizeOf(MyRecord));
  tmr1.Enabled := True;
end;

3. 读取数据

procedure TfrmClient.idpsrvr1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  SendData: TMyRecord;
begin
  ZeroMemory(@SendData, SizeOf(SendData));
  AData.Read(SendData, SizeOf(SendData));
  AddData(Format('IP: %s Port:%d  Data: %s',
    [SendData.Ip, SendData.Port, SendData.Data]));
end;

股票,证券等,用这个来发布行情数据,刷刷的。 UDP通信的优势 速度比TCP快。 UDP通信的缺点 一旦UDP包过大的话,也能正常工作。只是优势就丢失了。 idUdpClient 主要用于发送udp请求,在接收udp响应的时候是同步的,所以一定要设置超时,否则的话程序容易死。 idUpdServer 即能用于发送udp数据包,也能用于接收udp数据包。但是设计的主要目的还是用于收到udp数据包之后给于反馈。 UDP包的大小问题 资料1:以太网的MTU是1500字节,IP包头占20个字节,UDP首部占8个字节,也就是说实际数据应该小于1472字节. 资料2:鉴于Internet上的标准MTU值为576字节,所以我建议在进行Internet的UDP编程时.最好将UDP的数据长度控件在548字节(576-8-20)以内. 测试结果: 0-548字节:会完美的展现UDP协议的优势(速度刷刷的)。 大于1472字节以后的话,也可以正常执行。你会见识到什么叫做不可靠的信道(经过测试90%以上还是成功的,只是速度慢了很多)。 数据包大于2K速度明显变慢了;数据包大于3K,成功率60%到80%;数据包大于4k,成功率20%以下。 结论: 1.UDP协议还是比较可靠的。使用它能充分挖掘速度的潜力。通常大部分请求和相应都在548以下,小部分请求超过548。 2.548字节,可以存储274个汉字呢。比手机短信都长。你传什么那么大? 3.尤其是双方都在修改数据,需要实施数据实时同步的时候。修改量都比较小,用udp再合适不过了。 客户端的阻塞式响应不太理想 可以采用的办法是双方都开UDP服务器来接受。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值