2010-12-05 31 views
8

UDP C/Sを作成しています。サーバーが1秒間に受信できるデータの数に問題があります。DelphiのUDPサーバーとクライアント

私は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; 
... 
+0

wiresharkを使用してループバックudpトラフィックをログに記録できますか(Windowsではwinpcapで動作します)。 –

+0

私はまた、マイクロソフトの「セキュリティ」のパケット/秒の制限について検討します。 IIRC、tcpip.sysがイベントログにキャッピングアクションを報告しました –

+0

私はwiresharkを試しました。それが間違っているかどうかはわかりませんが、選択するループバックアダプタがあります。 :(素晴らしいツールtho。 – Darkerstar

答えて

13

UDPを保証するものではありませんメッセージ配信 - バッファに場所がない場合、パケットは躊躇せずにドロップされます。 保証された配信が必要な場合は、TCPを使用し、TCPの上にメッセージベースの通信スキームを構築します。既にご利用いただいているMsgConnect製品をご利用ください。十字軍のための注意:MsgConnectにはオープンソース版があります。

+1

+1非常に良い答え! – ComputerSaysNo

+0

バッファを大きくする方法、またはバッファの内容をより速く処理する方法はありますか? –

+3

@Robとは何ですか?巨大なバッファー(そして、あなたはできないでしょう。重い負荷ではバッファーサイズが十分であるという保証はありません。その場合のパケットの欠落は、追跡が困難なバグを引き起こします。だから、「欠陥のある」(この具体的な目的のために)アーキテクチャを使用しない方が良いでしょう。 –

3

UDPプロトコルを使用し、パケットを失わない場合は、UDPパケットが送信中に失われる可能性があるため、プログラムに肯定応答メカニズムを追加する必要があります。このACKメカニズムはTCPプロトコルにすでに実装されているため、パフォーマンスと一貫性のために最適な選択です。

TCPを使用できない場合(おそらく、クライアントがTCPを処理するのに十分なCPUパワーまたはRAMを持っていない場合)、TFTPなどのUDPベースのプロトコルを簡単にコーディングすることを検討してください。 SynCrtUnitでTFTPクライアントとサーバを実装しましたが、Synapseにこのようなコンポーネントがあります。しかし、TFTPはすべての送信パケットに対してACK信号を待つため遅いです。だから、パケットを失うことはありませんが、速度はTCPに比べて悪くなります。

私は昨年、このようなTFTPサーバーをDelphiで実装し、次にTP 7のTFTPクライアントをDOSベースの自動エンジンで実装しました。これはうまくいっていて、いくつかのオブジェクト構造が両端で共有されていました。 TFTP/UDP/IPスタックは、静的に割り当てられたメモリだけを持つ純粋なTP 7でコード化されていました。

しかし、このような「低CPU」要件がない場合は、UDP/IPの代わりにTCP/IPを使用することを検討してください。たとえば、放送が必要な場合は、UDPを使用しますが、何らかのACKメカニズムを使用します。

+0

ありがとう、私はそれをチェックアウトすることを確認します。 – Darkerstar

+2

実際に、保証された配信でUDPベースの通信を構築すると、TCPの速度を高速化することは難しく、数世代の開発者によって磨かれました。これは可能です(特定のタスクやアプリケーションではこれを行いました)が、それほど簡単ではありません。したがって、非アクティブ時に切断される可能性のあるTCPルートを使用するのがおそらく最善の方法です。 –