C++ 将不同类型的数据传递给void指针函数以添加到网络数据包(我想是吧?)

C++ 将不同类型的数据传递给void指针函数以添加到网络数据包(我想是吧?),c++,networking,void-pointers,C++,Networking,Void Pointers,编辑到代码最初发布时,我对以下代码的理解非常糟糕。最后我遇到的问题是,我得到的是我已经传递给函数的size值的“sizeof”。因此,我总是写4字节,而不是实际大小。基本上我是这样做的: size = sizeof(valueIWantToSend); finalSizeToWrite = sizeof(size); //derpderpderp 我已经修复了下面的示例代码 在创建要发送的网络数据包时,尝试做一些稍微复杂一点的事情来清理代码 其想法是具有如下功能: AppendPacket(

编辑到代码最初发布时,我对以下代码的理解非常糟糕。最后我遇到的问题是,我得到的是我已经传递给函数的size值的“sizeof”。因此,我总是写4字节,而不是实际大小。基本上我是这样做的:

size = sizeof(valueIWantToSend);
finalSizeToWrite = sizeof(size); //derpderpderp
我已经修复了下面的示例代码


在创建要发送的网络数据包时,尝试做一些稍微复杂一点的事情来清理代码

其想法是具有如下功能:

AppendPacket(dataToBeSent,sizeOfData)

我一直坚持的一点是通过这个函数正确地复制数据

以前,我会有几行凌乱的“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";
     }
}
unsigned char packetToBeSentBuffer[数据包大小];
无符号字符*bufferIndexCurrent;
无符号字符*bufferIndexStartPosition;
无符号字符*GetBufferPositionIndex();
void StepBufferPositionForward(int sizeOfVar);
无符号字符*GetBufferPositionIndex()
{
返回bufferIndexCurrent;
}
void PlayerObj::StepBufferPositionForward(int-sizeOfVar)
{
bufferIndexCurrent+=sizeOfVar;
如果(messageToSendIndex>((bufferIndexStartPosition+数据包大小)-200))
{

cout如果不知道代码最终是如何进行套接字读/写的,以及缓冲区是如何工作的,我不能完全确定确切的问题现在在哪里,但是现在有一个建议,可以进一步简化代码

代码仍然容易出错,因为您需要确保所传递数据的大小正确。如果新函数的复制粘贴错误且大小不正确,则会再次出现错误。对于这些情况,我始终建议使用一个简单的模板:

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);
模板
附加数据包(T&data)
{
std::size\u t size=sizeof(t);
memcpy(一些目的地和数据、大小);
前进步(大小);
}
结构,无论是什么;
附件(a);
双b;
附件(b);
int c[5]={1,2,3,4,5};
附件(c);
这样,编译器每次都会为您计算出数据的大小

关于缓冲区,具有固定大小会有问题,因为当前AppendPacket无法处理超过数据包大小的情况。有两种解决方案:

  • 获取要在缓冲区中写入的位置时引发异常
  • 具有可动态调整大小的缓冲区
我将举例说明如何处理第二种情况:

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) );
    }

}
类客户端
{
std::矢量下一个数据包;
公众:
模板
附件包(T&data)
{
//算出尺寸
std::size\u t size=sizeof(t);
//展开向量以容纳更多空间
下一包储备(大小);
//将数据附加到向量
标准::复制(静态转换和数据),
大小,
标准:背面插入器(下一个包装);
}
}

能否请您提供有关
GetBufferPositionIndex()
函数的详细信息?这些方法是类似于套接字的类吗?所有这些成员/方法都是同一类的一部分吗?还是全局的?我建议将它们设为“客户端”或“服务器”的一部分-处理数据包的人。固定的数据包大小也很容易出错-你可以随时超过它。是的,我可以做很多事情来改进数据包的创建和错误处理。我会在某个时候着手解决它。我目前的主要问题是数据的复制。这个答案的问题是,它不会增加根据我所知,在不进行重构的情况下,删除我的原始问题,我现在还不打算进行重构。另外,我需要学习更多关于模板的知识,因为我目前不使用模板。我需要找出为什么我要获取数据块的地址,而不是写入缓冲区的实际数据块。当您最初查看我的代码a时,我已经删除了上面我忘了添加一个非常重要的部分。我现在已经更新了示例。希望有人能利用你所做的:)嘿!你的解释没有解决你的问题吗?你传递了错误的大小,这导致了你的问题。你每次都手动传递大小,这就是为什么会发生错误的原因。我的第一个答案应该解决问题-如果你保持简单,模板不必变得复杂。把它看作是另一个参数
t
对于您的函数(
模板
),但它是一种类型,编译器会在编译时为您计算出来(无运行时成本)。这是一个双赢。是的,自从更新了我通过函数传递大小的方式后,它就如预期的那样工作了。我还没有实施你的模板建议,因为它太多了,我现在无法理解。Will lo