C++ 针对这种客户机/服务器情况(C+;+;),在一个头文件中包含多个结构

C++ 针对这种客户机/服务器情况(C+;+;),在一个头文件中包含多个结构,c++,data-structures,client-server,C++,Data Structures,Client Server,我在试着决定这是不是很好。 基本上,我正在编写一个客户机-服务器系统。为了简化和减少错误,我决定客户端和服务器之间的所有请求/响应/等都应定义为客户端和服务器都使用的共享库中的结构,然后有一个知道如何序列化结构的序列化层(两者都使用) 例如: 共享库: requestparamstructs.h #ifndef REQUEST_PARAMS_H #define REQUEST_PARAMS_H struct CreateUserRequestParams { std::string

我在试着决定这是不是很好。 基本上,我正在编写一个客户机-服务器系统。为了简化和减少错误,我决定客户端和服务器之间的所有请求/响应/等都应定义为客户端和服务器都使用的共享库中的结构,然后有一个知道如何序列化结构的序列化层(两者都使用)

例如:

共享库:

requestparamstructs.h

#ifndef REQUEST_PARAMS_H
#define REQUEST_PARAMS_H

struct CreateUserRequestParams
{
    std::string name;
    std::string address;
    std::string username;
    int age;
    ..
    ..
};

struct CreateItemRequestParams
{
    std::string name;
    std::string description;   
};

..
..

#endif
client.h

CreateUserRequestParams p;
p.name = "Foo";
p.address = "Somewhere";
p.username = "mrfoo";

Request<CreateUserRequestParams> myRequest(p);

client.queueRequest(myRequest);
然后在我客户的某个地方:

requestparamstructs.h

#ifndef REQUEST_PARAMS_H
#define REQUEST_PARAMS_H

struct CreateUserRequestParams
{
    std::string name;
    std::string address;
    std::string username;
    int age;
    ..
    ..
};

struct CreateItemRequestParams
{
    std::string name;
    std::string description;   
};

..
..

#endif
client.h

CreateUserRequestParams p;
p.name = "Foo";
p.address = "Somewhere";
p.username = "mrfoo";

Request<CreateUserRequestParams> myRequest(p);

client.queueRequest(myRequest);
client.h
CreateUserRequestParams p;
p、 name=“Foo”;
p、 address=“某处”;
p、 username=“mrfoo”;
请求我的请求(p);
client.queueRequest(myRequest);
然后服务器接收请求,用工厂创建适当的结构,并取消序列化并执行它需要执行的任何操作

现在,最初我将每个结构放在一个单独的文件中,但这似乎有些过分

像这样把这些结构放在一个标题中会让你不安吗?我想唯一缺少的是一个初始化变量的默认构造函数,这使它更像一个类,然后感觉它应该是单独的文件

请记住,我将需要创建很多这样的

谢谢

编辑:

requestparamstructs.h

#ifndef REQUEST_PARAMS_H
#define REQUEST_PARAMS_H

struct CreateUserRequestParams
{
    std::string name;
    std::string address;
    std::string username;
    int age;
    ..
    ..
};

struct CreateItemRequestParams
{
    std::string name;
    std::string description;   
};

..
..

#endif
client.h

CreateUserRequestParams p;
p.name = "Foo";
p.address = "Somewhere";
p.username = "mrfoo";

Request<CreateUserRequestParams> myRequest(p);

client.queueRequest(myRequest);
1) 只是澄清一下,这是一个通过TCP/IP进行通信的客户机-服务器系统。没有共享内存。“共享库”只是在.lib文件中共享代码并链接到中。客户端和服务器都可以使用的所有公共代码都放在这里

2) 我认为参数化模板会很棒,不幸的是VS2010不支持可变模板。有一次我在想这样的事情:

template <Protocol::ClientRequest RequestCode, typename P1>
class RequestP1 : public Request
{
public:
    RequestP1() : Request(RequestCode) {}
    RequestP1(P1 p1) : Request(RequestCode), m_p1(p1) {}
    virtual void serialize(IArchive &ar)
    {
        serialize(ar, m_p1);
    }
    P1 m_p1;
};

template <Protocol::ClientRequest RequestCode, typename P1, typename P2>
class RequestP2 : public Request
{
public:
    RequestP2() : Request(RequestCode) {}
    RequestP2(P1 p1, P2 p2) : Request(RequestCode), m_p1(p1), m_p2(p2) {}
    virtual void serialize(IArchive &ar)
    {
        serialize(ar, m_p1);
        serialize(ar, m_p2);
    }
    P1 m_p1;
    P2 m_p2;
};

..
..
模板
类RequestP1:公共请求
{
公众:
RequestP1():请求(RequestCode){}
请求P1(P1):请求(请求代码),m_P1(P1){}
虚拟空序列化(IArchive&ar)
{
序列化(ar,m_p1);
}
P1 m_P1;
};
模板
类RequestP2:公共请求
{
公众:
RequestP2():请求(RequestCode){}
请求P2(P1,p2p2):请求(请求代码),m_P1(P1),m_P2(P2){}
虚拟空序列化(IArchive&ar)
{
序列化(ar,m_p1);
序列化(ar,m_p2);
}
P1 m_P1;
p2m_P2;
};
..
..
这将允许我这样做:

typedef RequestP1<Protocol::CreateUser, CreateUserRequestParams> RequestCreateUser;

OR specifying the actual params (just showing the first two params here, name and address):

typedef RequestP1<Protocol::CreateUser, std::string, std::string> RequestCreateUser;
typedef RequestP1 RequestCreateUser;
或指定实际参数(仅在此处显示前两个参数,名称和地址):
typedef RequestP1 RequestCreateUser;
希望这是有道理的

像这样把这些结构放在一个标题中会让你不安吗

没有

假设服务器和客户端都使用最多(如果不是全部)的请求(因此“<代码> *PARAMS:/COD>两个对象都使用”),唯一使我考虑将它们放入单独文件的是它们的字段类型。

只要参数对象只有原语或普通类型,比如
std::string
,我就可以了。但是,如果您恰好引入了一个消息,该消息使用了标准库中未定义的类型(例如一个或类似的),我会考虑将该消息(和具有相同依赖性的其他消息)移到单独的文件中,以便只有那些需要使用这些参数的客户端才必须拉入依赖关系。我怀疑这在您的情况下是不可能的,因此将所有
Param
结构放在一个文件中是可以的

但是,如果发现不同客户端使用的*PARAM对象有很大的差异,我会考虑将相关的组放到单独的文件中以减少编译时依赖性。否则,向组中添加新的参数类型意味着重新编译所有客户机,即使是那些不使用相应消息的客户机

像这样把这些结构放在一个标题中会让你不安吗

没有

假设服务器和客户端都使用最多(如果不是全部)的请求(因此“<代码> *PARAMS:/COD>两个对象都使用”),唯一使我考虑将它们放入单独文件的是它们的字段类型。

只要参数对象只有原语或普通类型,比如
std::string
,我就可以了。但是,如果您恰好引入了一个消息,该消息使用了标准库中未定义的类型(例如一个或类似的),我会考虑将该消息(和具有相同依赖性的其他消息)移到单独的文件中,以便只有那些需要使用这些参数的客户端才必须拉入依赖关系。我怀疑这在您的情况下是不可能的,因此将所有
Param
结构放在一个文件中是可以的


但是,如果发现不同客户端使用的*PARAM对象有很大的差异,我会考虑将相关的组放到单独的文件中以减少编译时依赖性。否则,向组中添加新的参数类型意味着重新编译所有客户端,即使是那些不使用相应消息的客户端。

您可能会创建一个模板类来处理打包和解包消息,然后可能还会创建一系列用于不同参数的模板结构。。。如果您的编译器支持这个新的C++0x功能,也可以使用可变模板。AJG85:不幸的是,我使用的是VS2010(没有可变模板)。我曾经提出过这样的想法:模板类RequestP2(Param1&p1,Param2&p1){…}等等。。如果你是这个意思?所以我可以做:typedef RequestP2 RequestCreateUser;RequestCreateUser r(“Foo”,“某处”);-反正是这样的。这就是你的意思吗?@Mark yeah或多或少让我看看我是否可以发布一些有意义的内容作为答案。@AJG85:好的,谢谢:-)PS请查看编辑内容。@Mark实际上那些模板看起来不错