通过socket发送struct;服务器和客户端在同一台机器上

时间:2010-08-31 12:03:34

标签: c++ visual-c++

我的服务器和客户端在同一台机器上运行,所以我没有端点问题等。我需要一些适用于vc ++和g ++的东西,可能是最简单的方法。我可以用结构发送什么?

修改

struct Info
{
     int**   fields; 
     char**  field_names;
};

4 个答案:

答案 0 :(得分:1)

请看Boost.Serialization,这是我在another question发布的一个相当简单的例子

#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/string.hpp>

#include <string>

struct Message
{
    std::string _a;
    std::string _b;

    template <class Archive>
    void serialize(
            Archive& ar,
            unsigned int version
            )
    {
        ar & _a;
        ar & _b;
    }
};

int
main()
{
    Message msg;
    msg._a = "hello";
    msg._b = "world";
    std::ostringstream os;
    boost::archive::text_oarchive ar( os );
    ar & msg;
}

请注意,序列化库具有比此更多的功能。它可以序列化其他Boost库中的指针,引用,容器和许多对象。我的示例显示了侵入式序列化,如果您无法修改结构,还有一些方法可以序列化non-intrusively

答案 1 :(得分:0)

您需要确保在VC ++和G ++中使用的数据成员具有相同的字节大小和对齐方式。

如果你有一个可变长度的数据成员,那么通过套接字传输它的最佳方法就是发送大小。

假设你有这样的结构:

struct DataStruct
{
   int x;
   char* message;
   short messageLen;
}

您可以通过套接字(每个成员的成员)以指定格式发送数据,因为您知道非预定义大小成员的大小。

G ++和G ++中的整数是4个字节。 VC ++;字符都是1个字节;短裤是2个字节。

首先传输x值,然后传递messageLen var并使用此变量在另一侧创建变量缓冲区大小。然后,您可以将消息数据写入char *。

答案 2 :(得分:0)

您拥有的结构具有指向数据的指针,而不是数据本身。如果你在结构中使用POD类型(即int和char []),那么它可以直接在套接字上发送。

由于结构中的对齐/填充,可能会传输一些额外的字节,但是如果您对此有好处,那么您可以继续使用。这是因为您在同一操作系统上运行客户端和服务器。如果涉及不同的操作系统,则对齐/填充会产生问题。

boost::asio有一些非常简单的示例供您使用。

答案 3 :(得分:0)

您可以像这样声明一个静态无符号字符:

#define MSGBUFSIZE  512
static unsigned char ClientSendBuf[MSGBUFSIZE];

然后将您的结构复制到数组中,如下所示:

memmove(&ClientSendBuf[2], &struct, sizeof(struct));

现在这是下一个特定于实现的地方。我正在使用Borland C ++,所以我的发送行为就像这样:

ClientSocket->Socket->SendBuf(ClientSendBuf, ClientSendBuf[0]+CRC16SIZE);

我使用ClientSendBuf [0]的原因是因为我的消息大小存储在ClientSendBuf [0]中,如下所示:

ClientSendBuf[0] = 4 + sizeof(struct);             //Byte Count

(注意:将struct替换为struct的名称)

我还在消息的末尾添加了一个CRC校验,如下所示:

#define CRC16SIZE   2

...

cs = CheckSum((unsigned char *)ClientSendBuf, ClientSendBuf[0]);
    memmove(&ClientSendBuf[ClientSendBuf[0]], &cs, CRC16SIZE);

...

unsigned short __fastcall TFormMenu::CheckSum(unsigned char *p, int length)
{
    int i;

    for (cs = 0, i = 0; i < length; i++) {
        cs += p[i];
    }
    return cs;
}

基本上所有这些简单的CRC校验都是对所有字节求和,以确定发送正确的字节数。如果数据应该被破坏(顺便说一下,通过有缺陷的WiFi连接是常见的),那么服务器应该抛出CRC错误。

这都假设你有一个POD结构。 static部分不是必需的,但我是如何在我的特定应用程序中完成的。我还掩饰了一些细节。如果您有任何疑问,请在评论中发帖。因人而异。