Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UDP Server and Client in Delphi

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;
...
like image 940
Darkerstar Avatar asked Dec 05 '10 15:12

Darkerstar


2 Answers

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.

like image 31
Arnaud Bouchez Avatar answered Oct 02 '22 06:10

Arnaud Bouchez


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.

like image 165
Eugene Mayevski 'Callback Avatar answered Oct 02 '22 06:10

Eugene Mayevski 'Callback