2016-04-30 26 views
1

私は現在ゲーム用に小さなUDPサーバーを作成するためにDを使用しています。問題は、受信した一部のパケットが実際のパケットの長さに一致しないことです(wireshark経由で表示)。D受信全パケットを受信して​​いません

たとえば、クライアントはネットワーク経由で110バイトのパケットを送信します。これはwiresharkの下に表示されます。しかし、Dコードは7バイトしか受信しません!他の7バイトのパケットは、クライアントからネットワークを介して送信されることはありません。

Dからの7バイトは、110バイトパケットから最初の7バイトに一致します。私はこの問題を引き起こす可能性のあることは考えられないので、ソケットライブラリの問題だと思う。

問題は、常に同じポイントとまったく同じパケットで発生します。無視すると、問題は特定のパケットに対して継続されます。

このプロジェクトでは、複数のファイルがあることに注意してください、私は以下のコードの切れ端含めてください:

this(in Logger logger, string bindInterface = "0.0.0.0", ushort bindPort = 19132) { 
    this.logger = logger; 
    socket = new UdpSocket(AddressFamily.INET); 
    bindAddress = new InternetAddress(bindInterface, bindPort); 
} 

void bind(uint sendBufferSize = 1024 * 1024, uint recvBufferSize = 1024 * 1024) { 
    socket.bind(bindAddress); 

    socket.setOption(SocketOptionLevel.SOCKET, SocketOption.BROADCAST, true); 
    socket.setOption(SocketOptionLevel.SOCKET, SocketOption.SNDBUF, sendBufferSize); 
    socket.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVBUF, recvBufferSize); 
    socket.blocking = false; 
} 

bool recv(ref Address address, ref byte[] buffer) { 
    auto length = socket.receiveFrom(buffer, SocketFlags.NONE, address); 
    if(length > 0) { 
     buffer.length = length; 
     debug logger.logDebug(to!string(length) ~ " Packet IN: " ~ to!string(cast(ubyte[]) buffer)); 
     return true; 
    } 
    buffer = null; 
    return false; 
} 

を...

Address a; 
    byte[] data = new byte[1024 * 1024]; 
    while(max-- > 0 && socket.recv(a, data)) { 
     handlePacket(a, data); 
    } 

完全なソースはhere.

を見つけることができます

ご協力いただければ幸いです。 ref

bool recv(ref Address address, ref byte[] buffer) 

あなたはスライスを作成しませんが、前のパケットが7bytes限り、あなたはより多くを受け取ることができないよりもあるので、もしあなたが本当に元のバッファを変更します。

クライアントは

+0

送信されるメッセージ全体の正確な内容を確認できますか?あなたが信じているものではなく、実際にどのようなコンテンツが送られているのですか? – zipzit

+0

それはありそうもありません。 UDPは完全なメッセージを送信するか、何も送信しません。これは、UDPが行う唯一の保証です。あなたが言うことが真実なら、ネットワークインフラストラクチャ、OS、コードコンパイラで何かが非常に壊れています。 – jgauffin

+0

@zipzit wiresharkを使用している場合、はい、コンテンツ全体が表示されます。問題のデータはRakNetプロトコルのバイナリハンドシェイクパケットの一部です。 – jython234

答えて

3

問題は、この行にされていますより7つのバイトはもう

は、だから、REFを削除し、代わりにプレーンなブール値の長さを返すようにコードを変更することができます

size_t recv(ref Address address, byte[] buffer); 

、その後:

Address a; 
byte[] data = new byte[1024 * 1024]; 
size_t len; 
while(max-- > 0 && (len = socket.recv(a, data))) { 
    handlePacket(a, data[0 .. len]); 
} 

しかし、これはおそらく別のrefのごhandlePacket機能が動作しないだろうので、別の変形例では、コードのあなたのrecvなく、一部だけがhandlePacket

Address a; 
byte[] data = new byte[1024 * 1024]; 
size_t arr = data[]; 
while(max-- > 0 && socket.recv(a, arr)) { 
    handlePacket(a, arr); 
    arr = data[]; 
} 
をarount変更しないことです
+0

彼は 'handlePacket'に対して更新された' .length'が必要なので、単にrefを削除することはできません。しかし、1つ目の問題は、最初のrecv呼び出しの後に 'receiveFrom'に渡される' data'バッファーが小さすぎることです。可能な解決策: 'ref'を削除して、' recv'から更新されたスライスを返し、 'handlePacket'のためにそれを使用します。または、 'recv'を変更せずに' handlePacket'の後に 'data'を完全なバッファサイズにリセットしてください。 – jpf

+0

@jpfはい、答えをより正確にするように変更しました – Kozzi11

+0

refバイト[]バッファが7バイトしか受け付けない理由について詳しく調べてください。それは私には意味をなさない。 –

関連する問題