Delphi中的UDP服务器和客户端
我正在做一个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;
...
I am making a UDP C/S. I am having a problem with number of data the server can receive per second.
I have tested sending batches of 10, 100, 1000 data messages to the server, 10, 100 received without a problem. when sending 1000, only 300 ~ 400 received. All tests done on locally.
I have tried implement the server using both ICS's twsocket and Synapse's tudpblocksocket. Both turned out with same problem above.
Could any explain to me why this happens, and how could I improve the server performance.
Code using 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;
...
Code using 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;
...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
UDP 不保证消息传送 - 如果缓冲区中没有位置,则数据包会被毫不犹豫地丢弃。
如果您需要有保证的交付,请使用 TCP 并在 TCP 之上构建基于消息的通信方案。或者使用我们已有的 MsgConnect 产品。十字军注意:MsgConnect 有一个开源版本。
UDP doesn't guarantee message delivery - if there's no place in the buffer, the packet is dropped without hesitation.
If you need guaranteed delivery, use TCP and build a message-based communication scheme on top of TCP. Or use our MsgConnect product which already has it. Note for crusaders: MsgConnect has an open-source version.
如果你想使用UDP协议并且不丢失任何数据包,你必须在你的程序中添加一个Acknowledge机制,因为UDP数据包在传输过程中可能会丢失。这种ACK机制已经在TCP协议中实现,因此它是性能和一致性的最佳选择。
如果您无法使用 TCP(可能您的客户端没有足够的 CPU 能力或 RAM 来处理 TCP),请考虑使用一些易于编码的基于 UDP 的协议,例如 TFTP。我们通过 SynCrtUnit 实现了 TFTP 客户端和服务器,但您有这样一个组件在突触中。但 TFTP 速度很慢,因为它等待每个传输数据包的 ACK 信号。所以你不会丢失任何数据包,但与 TCP 相比,速度会很差。
去年,我在 Delphi 中实现了这样的 TFTP 服务器,然后在基于 DOS 的自动化引擎中的 TP 7 中实现了 TFTP 客户端。这非常有效,并且一些对象结构在两端之间共享。 TFTP/UDP/IP 堆栈采用纯 TP 7 进行编码,仅使用静态分配的内存,并且运行良好。
但如果您没有如此“低 CPU”的要求,请考虑使用 TCP/IP 而不是 UDP/IP。例如,如果您需要一些广播,则使用 UDP,但使用某种 ACK 机制。
If you want to use UDP protocol and don't loose any packet, you'll have to add an Acknowledge mechanism to your program, because UDP packets can get lost during the transmission. This ACK mechanism is already implemented in the TCP protocol, so it's the best choice for performance and consistency.
If you can't use TCP (perhaps your client don't have enough CPU power or RAM to handle TCP), consider using some easy to code UDP based protocol, like TFTP. We implemented a TFTP client and server over our SynCrtUnit, but you have such a component in Synapse. But TFTP is slow, because it wait for an ACK signal for every transmitted packet. So you won't loose any packet, but the speed will be poor, compared to TCP.
Last year, I've implemented such TFTP Server in Delphi, then a TFTP Client in TP 7, in a DOS-based automated engine. This was working great, and some object structures were shared between both ends. The TFTP/UDP/IP stack was coded in pure TP 7, with only static allocated memory, and was working great.
But if you don't have such "low CPU" requirements, rather consider using TCP/IP instead of UDP/IP. If you need some broadcasting for example, then use UDP, but with some kind of ACK mechanism.