【问题标题】:UDP Server and Client in DelphiDelphi中的UDP服务器和客户端
【发布时间】:2011-05-20 13:35:46
【问题描述】:

我正在制作一个 UDP C/S。我对服务器每秒可以接收的数据数量有疑问。

我已经测试了将 10、100、1000 条数据消息批量发送到服务器,10、100 条接收没有问题。发送 1000 时,只收到 300 ~ 400。所有测试都在本地完成。

我已经尝试使用 ICS 的 twsocket 和 Synapse 的 tudpblocksocket 来实现服务器。两者都出现了上述相同的问题。

能否向我解释为什么会发生这种情况,以及如何提高服务器性能。

使用 TUDPBlockSocket 的代码

...

while not Terminated do
begin
  try
    sz := FUDPServer.WaitingData;
    if sz > 0 then
    begin
      FUDPServer.RecvBuffer(mem.Memory, sz);
      mem.Seek(0, 0);
      AMessage := fFormats.ReadFromStream(mem);
      DoMessageReceived(FUDPServer.RemoteSin.sin_addr, AMessage);
    end; 

  finally

  end;
end;

...

使用 ICS 的代码

...

procedure TShapeServer.WSocketDataAvailable(Sender: TObject; ErrCode: Word);
...
begin
  SrcLen := SizeOf(Src);
  stream := TMemoryStream.Create;
  stream.SetSize(INT_BUFFER_SIZE);
  Inc(fMessageReceived);  
  try
    Len    := FUDPServer.ReceiveFrom(stream.Memory, stream.size, Src, SrcLen);
    if (FSenderAddr.S_addr = INADDR_ANY) or
       (FSenderAddr.S_addr = Src.Sin_addr.S_addr) then
    begin

      while stream.Position < Len do
      begin
        try
          AMessage := fFormats.ReadFromStream(stream);
          DoMessageReceived(Src.Sin_addr, AMessage);
        except
          break;
        end;
      end;

    end;

  finally
    stream.Free;
  end;
end;
...

【问题讨论】:

  • 你能用wireshark记录环回udp流量吗(在Windows上它与winpcap一起工作)?
  • 我还会研究微软每秒数据包的“安全”限制。 IIRC,tcpip.sys 向事件日志报告了上限操作
  • 我试过wireshark。不确定是否做错了,但有环回适配器供我选择。 :( 很棒的工具。

标签: delphi sockets udp


【解决方案1】:

UDP 不保证消息传递 - 如果缓冲区中没有位置,数据包会毫不犹豫地丢弃。 如果您需要保证交付,请使用 TCP 并在 TCP 之上构建基于消息的通信方案。或者使用我们已经拥有的MsgConnect 产品。十字军注意事项:MsgConnect 有一个开源版本。

【讨论】:

  • 那么,有没有办法让缓冲区更大,或者更快地处理缓冲区的内容?
  • @Rob 是什么原因?即使您可以使缓冲区变大(并且您不能_,您也不能保证在较重的负载下缓冲区大小就足够了。在这种情况下丢包会导致难以跟踪的错误。所以最好不要使用“有缺陷的”(为此具体目的)架构
  • @Darkerstar 您是为 LAN 开发应用程序还是为 Internet 开发应用程序?使用 Internet 的问题是每个路由器也有不同的缓冲区,并且那里的数据丢失会更频繁。
  • @Darkerstar 那么我建议您在投入更多时间在此架构上之前立即进行性能测试。在现实生活中,损失率可能会变得无法接受。
  • 致过分热心的垃圾邮件举报者:并非所有指向营利性产品的链接都是垃圾邮件。这篇文章符合self promotion 下的常见问题解答中提到的所有准则。
【解决方案2】:

如果你想使用 UDP 协议并且不丢失任何数据包,你必须在你的程序中添加一个确认机制,因为 UDP 数据包在传输过程中可能会丢失。这种ACK机制已经在TCP协议中实现,是性能和一致性的最佳选择。

如果您不能使用 TCP(可能您的客户端没有足够的 CPU 功率或 RAM 来处理 TCP),请考虑使用一些易于编码的基于 UDP 的协议,例如 TFTP。我们通过SynCrtUnit 实现了一个 TFTP 客户端和服务器,但是您在 Synapse 中有这样一个组件。但是 TFTP 很慢,因为它等待每个传输的数据包的 ACK 信号。所以你不会丢失任何数据包,但与 TCP 相比,速度会很差。

去年,我在基于 DOS 的自动化引擎中在 Delphi 中实现了这样的 TFTP 服务器,然后在 TP 7 中实现了 TFTP 客户端。这工作得很好,两端共享一些对象结构。 TFTP/UDP/IP 堆栈是在纯 TP 7 中编码的,只有静态分配的内存,并且运行良好。

但如果您没有这种“低 CPU”要求,请考虑使用 TCP/IP 而不是 UDP/IP。例如,如果您需要一些广播,则使用 UDP,但使用某种 ACK 机制。

【讨论】:

  • 谢谢,我一定会去看看的。
  • 事实上,当您构建基于 UDP 并保证交付的通信时,很难在速度上与 TCP 相提并论:几代开发人员都在打磨它。这是可能的(我们为某些特定的任务和应用程序这样做)但非常重要。因此,在不活动时可能会断开连接的 TCP 路由可能是最好的方法。
猜你喜欢
  • 2014-08-12
  • 2012-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-22
  • 2012-01-04
  • 1970-01-01
相关资源
最近更新 更多