0

コードへの編集最初に投稿したとき、以下のコードで本当にひどいことをしました。最終的に私が抱えていた問題は、既に関数に渡したサイズ値の「sizeof」を取得していたことです。したがって、実際のサイズではなく、常に 4 バイトを書いていました。基本的に私はこのようなことをしました:

size = sizeof(valueIWantToSend);
finalSizeToWrite = sizeof(size); //derpderpderp

以下のサンプルコードを修正しました。


送信するネットワーク データのパケットを作成するときにコードをクリーンアップするために、もう少し複雑なことをしようとしました。

アイデアは、次のような機能を持つことです。

AppendPacket(dataToBeSent, sizeOfData)

私が立ち往生している部分は、この関数を介して dataToBeSent を正しくコピーすることです。

以前は、指定された位置のバッファにデータを詰め込む "memcopy" の乱雑な行がいくつかありました。この方法は機能し、試行錯誤されています。以下の例にもかかわらず、それは面倒で維持するためのペイントです。

memcpy((char*)GetBufferPositionIndex(), (char*)&dataToBeSent, sizeof(sizeof(dataToBeSent)));
StepBufferPositionForward(sizeof(dataToBeSent));

これは、マルチプレイヤー クライアントに送信する必要があるデータをパッケージ化するために、ゲーム コード全体のさまざまな場所で現在使用しているものの、よりわかりやすいバージョンです。

これらの行をあちこちにコピーする代わりに、AppendPacket() 関数を使用したいと思います。最初は次のようになります。

//How I tend to use the function in my code
double playerVelocity = 22.34;
AppendPacket( &playerVelocity, sizeof(playerVelocity) );


//Definition
AppendPacket( void* dataToBeSent, size_t sizeOfData )
{
     memcpy( (char*)GetBufferPositionIndex(), dataToBeSent, sizeof(sizeOfData) );
     StepBufferPositionForward( sizeof(sizeOfData) );
}

デバッグでわかることは、実際のデータ自体ではなく、実際にデータのアドレスを送信していることです。

関数と「dataToBeSent」部分を介してポインター記号とアドレス記号のさまざまな組み合わせを試しましたが、運がありません:(

上記は、構造体、文字配列、シングルバイト、倍精度浮動小数点数、整数、浮動小数点数など、あらゆる種類のデータ形式で動作する必要があります。

私がどのようにそれをしていると思われるかについてのアイデアはありますか? 朝から晩まで頭を悩ませています :(


興味深いことに、GetBufferPositionIndex()は基本的に、バッファ内で次に書き込みを開始する位置を返します。

unsigned char packetToBeSentBuffer[PACKET_SIZE];
unsigned char* bufferIndexCurrent;
unsigned char* bufferIndexStartPosition;

unsigned char* GetBufferPositionIndex();
void StepBufferPositionForward(int sizeOfVar);

unsigned char* GetBufferPositionIndex()
{
     return bufferIndexCurrent;
}

void PlayerObj::StepBufferPositionForward(int sizeOfVar)
{
     bufferIndexCurrent += sizeOfVar;
     if (messageToSendIndex > (( bufferIndexStartPosition + PACKET_SIZE) - 200))
     {
           cout << "WARNING: Packet for this tick has less than 200 bytes left until full\n";
     }
}
4

1 に答える 1

2

コードが最終的にソケットの読み取り/書き込みにどのように到達するか、およびバッファがどのように機能するかを知らずに、正確な問題が現在どこにあるのか完全にはわかりませんが、コードをさらに簡素化するための提案をここに示します。

渡すデータのサイズが正しいことを確認するのはユーザー次第であるため、コードは依然としてエラーが発生しやすいです。新しい関数を間違ったサイズでコピーして貼り付けると、再びバグが発生します。これらのケースでは、私はいつもシンプルなテンプレートを提案しています:

template <typename T>
AppendPacket( T& data )
{
    std::size_t size = sizeof(T);
    memcpy( some_destination, &data, size );
    StepBufferPositionForward( size );
}

struct whatever a;
AppendPacket(a);

double b;
AppendPacket(b);

int c[5] = {1, 2, 3, 4, 5};
AppendPacket(c);

このようにして、コンパイラは毎回データのサイズを計算します。

バッファについては、現在 AppendPacket はパケット サイズを超えた場合に対応していないため、サイズを固定すると問題が発生します。次の 2 つの解決策があります。

  • バッファ内の書き込み位置取得時に例外をスローする
  • 動的にサイズ変更可能なバッファを持つ

2 番目のケースを処理する方法の例を示します。

class Client
{
    std::vector<char> nextPacket;

public:

    template <typename T>
    AppendToPacket( T& data )
    {
        // figure out the size
        std::size_t size = sizeof(T);

        // expand vector to accomodate more space
        nextPacket.reserve(size);

        // append the data to the vector
        std::copy_n( static_cast<char const*>(&data),
                     size,
                     std::back_inserter(nextPacket) );
    }

}
于 2012-12-27T03:05:45.187 に答える