socket中该如何封装message

xiaoyaoxiaonizi 2013-11-02 03:38:32
大家好,最近在写一个聊天程序,能够简单的文字对话。现在在完善周边功能,比如登录登出,发送附件,检验掉线等。现在遇到一个问题,就是随着message类型增多,服务器和客户端的逻辑也越来越复杂,所以想把message单独封装成一个类。我的想法是server类只负责数据包的传输,数据的解析工作最好全部由message类完成。这样既降低了server类的复杂度,后期新增新的消息类型也比较容易添加。
我想使用继承来实现message类,比如基类为

class Messagebase
{
void *GenerateMsg();//这里该如何传入数据,因为每个子类需要的数据类型都不一样,所以没法写出一个通用的函数。
void ParaseMsg(void *data, int len);
}

其中我比较头疼的是数据在server和message类之间如何传递,为了实现上述类中的函数统一性,最好在类设计上不要暴露数据细节,最好是通用的。
大家有没有好的想法,请告诉我,或者你们以前是怎么去做的,我们一起讨论讨论吧。
要是能得到灵感,比有重赏。
...全文
449 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2013-11-04
  • 打赏
  • 举报
回复
不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊! http://topic.csdn.net/u/20120210/09/51109ed0-07b9-41f2-b487-a51597f2ca01.html
qq120848369 2013-11-03
  • 打赏
  • 举报
回复
这种情况是需要一个向下转换的, 没有什么好办法.
pathletboy 2013-11-02
  • 打赏
  • 举报
回复
引用 12 楼 xiaoyaoxiaonizi 的回复:
[quote=引用 11 楼 pathletboy 的回复:] [quote=引用 10 楼 xiaoyaoxiaonizi 的回复:] [quote=引用 7 楼 pathletboy 的回复:] [quote=引用 6 楼 xiaoyaoxiaonizi 的回复:] [quote=引用 1 楼 pathletboy 的回复:] 派生类重载GenerateMsg函数实现。
GenerateMsg重载的时候传入数据该如何设计呢?每个类型的message需要的数据都不一样[/quote] 传void*[/quote] 是个方法,但如果我传void*,那server就需要为message组件数据,那server就需要知道每种message的数据格式,而且每个message需要定义一套公开的结构体用于数据传递。能不能有一种方法把这些全部隐藏起来,其实我预期的效果是,对于server,所有数据都是不透明的,server接收到数据直接丢给message处理。同样,如果server想发送一个消息,就像message申请,然后message告诉server需要哪些数据,server提供了相应的数据,message再把组装好的数据丢给server,server直接发送。[/quote] http://ideone.com/jOmFOz 写了个小例子,看看是不是你想要的。[/quote] 还是程序直观,看了程序我能得到不少启发。但你main函数在调用每个派生类的时候还是需要区分并传递对应的数据类型,这样如果message修改了传入数据,main函数也要一起改。能不能设计一个流程,由message告诉main函数我需要传递哪些数据,然后main再传入。[/quote] 实际使用应该这样,所有消息都通过基类指针访问CMessageBase* message; 然后根据你包体命令字,一般开头1字节 2字节 或者 4字节等等, switch(cmd){ case MT_PERSON: message = new CPersonMessage; break; case MT_CAR: message = new CCarMessage; break; } 然后message->GenerateMsg(传入void*)进行处理。
xiaoyaoxiaonizi 2013-11-02
  • 打赏
  • 举报
回复
引用 11 楼 pathletboy 的回复:
[quote=引用 10 楼 xiaoyaoxiaonizi 的回复:] [quote=引用 7 楼 pathletboy 的回复:] [quote=引用 6 楼 xiaoyaoxiaonizi 的回复:] [quote=引用 1 楼 pathletboy 的回复:] 派生类重载GenerateMsg函数实现。
GenerateMsg重载的时候传入数据该如何设计呢?每个类型的message需要的数据都不一样[/quote] 传void*[/quote] 是个方法,但如果我传void*,那server就需要为message组件数据,那server就需要知道每种message的数据格式,而且每个message需要定义一套公开的结构体用于数据传递。能不能有一种方法把这些全部隐藏起来,其实我预期的效果是,对于server,所有数据都是不透明的,server接收到数据直接丢给message处理。同样,如果server想发送一个消息,就像message申请,然后message告诉server需要哪些数据,server提供了相应的数据,message再把组装好的数据丢给server,server直接发送。[/quote] http://ideone.com/jOmFOz 写了个小例子,看看是不是你想要的。[/quote] 还是程序直观,看了程序我能得到不少启发。但你main函数在调用每个派生类的时候还是需要区分并传递对应的数据类型,这样如果message修改了传入数据,main函数也要一起改。能不能设计一个流程,由message告诉main函数我需要传递哪些数据,然后main再传入。
pathletboy 2013-11-02
  • 打赏
  • 举报
回复
引用 10 楼 xiaoyaoxiaonizi 的回复:
[quote=引用 7 楼 pathletboy 的回复:] [quote=引用 6 楼 xiaoyaoxiaonizi 的回复:] [quote=引用 1 楼 pathletboy 的回复:] 派生类重载GenerateMsg函数实现。
GenerateMsg重载的时候传入数据该如何设计呢?每个类型的message需要的数据都不一样[/quote] 传void*[/quote] 是个方法,但如果我传void*,那server就需要为message组件数据,那server就需要知道每种message的数据格式,而且每个message需要定义一套公开的结构体用于数据传递。能不能有一种方法把这些全部隐藏起来,其实我预期的效果是,对于server,所有数据都是不透明的,server接收到数据直接丢给message处理。同样,如果server想发送一个消息,就像message申请,然后message告诉server需要哪些数据,server提供了相应的数据,message再把组装好的数据丢给server,server直接发送。[/quote] http://ideone.com/jOmFOz 写了个小例子,看看是不是你想要的。
xiaoyaoxiaonizi 2013-11-02
  • 打赏
  • 举报
回复
引用 7 楼 pathletboy 的回复:
[quote=引用 6 楼 xiaoyaoxiaonizi 的回复:] [quote=引用 1 楼 pathletboy 的回复:] 派生类重载GenerateMsg函数实现。
GenerateMsg重载的时候传入数据该如何设计呢?每个类型的message需要的数据都不一样[/quote] 传void*[/quote] 是个方法,但如果我传void*,那server就需要为message组件数据,那server就需要知道每种message的数据格式,而且每个message需要定义一套公开的结构体用于数据传递。能不能有一种方法把这些全部隐藏起来,其实我预期的效果是,对于server,所有数据都是不透明的,server接收到数据直接丢给message处理。同样,如果server想发送一个消息,就像message申请,然后message告诉server需要哪些数据,server提供了相应的数据,message再把组装好的数据丢给server,server直接发送。
mujiok2003 2013-11-02
  • 打赏
  • 举报
回复
Sender : message text(xml or json)-------message writer(dll)-------> binary data ----(nework)------> binary data -----message reader(dll) --->message text(xml or json): Recever 1. 消息定义文本定式,以增加灵活性。 你可以定义不同的类型来表示不同消息,只要它可以序列化/反序列化为xml/json等文本就行。 2. 网络中传输的是经过编码,压缩待处理后的二进制数据,更安全,更高效。 编码器、解码器最好以dll的形式发布,后期维护更简单(升级的时候只要替换相应的dll即可)
xiaoyaoxiaonizi 2013-11-02
  • 打赏
  • 举报
回复
引用 4 楼 wjf8882300 的回复:
像SOCKET包通常开始就要定义好了,而且为每个业务写一个MESSAGE解析类的方法也不好。遇到这种情况通常分两种,一种就是开始就知道SOCKET每个域存储的内容和大小。像银行的8583规范就定义了128个域,把很多可能涉及到的业务都考虑到了,针对报文的解析就一种方法。第二种就是业务容易变化的,不知道SOCKET域的组成,可以采用XML报文的方法,XML报文其实可以采用树的数据结构来存储,每个节点采用键值对来表示,这种方式很灵活。
因为只是一个预演的程序,所以目前不太好确定所有消息类型,第二种方式比较吸引人,能具体说下吗?xml应该只是socket数据传输格式,message与server之间的传输如何解决?
pathletboy 2013-11-02
  • 打赏
  • 举报
回复
引用 6 楼 xiaoyaoxiaonizi 的回复:
[quote=引用 1 楼 pathletboy 的回复:] 派生类重载GenerateMsg函数实现。
GenerateMsg重载的时候传入数据该如何设计呢?每个类型的message需要的数据都不一样[/quote] 传void*
xiaoyaoxiaonizi 2013-11-02
  • 打赏
  • 举报
回复
引用 1 楼 pathletboy 的回复:
派生类重载GenerateMsg函数实现。
GenerateMsg重载的时候传入数据该如何设计呢?每个类型的message需要的数据都不一样
xiaoyaoxiaonizi 2013-11-02
  • 打赏
  • 举报
回复
引用 2 楼 focuslight 的回复:
每个子类需要的数据类型都不一样, 设计用工厂模式, CMessageFacetory CConcertMessage
能具体一点吗?谢谢
wjf8882300 2013-11-02
  • 打赏
  • 举报
回复
像SOCKET包通常开始就要定义好了,而且为每个业务写一个MESSAGE解析类的方法也不好。遇到这种情况通常分两种,一种就是开始就知道SOCKET每个域存储的内容和大小。像银行的8583规范就定义了128个域,把很多可能涉及到的业务都考虑到了,针对报文的解析就一种方法。第二种就是业务容易变化的,不知道SOCKET域的组成,可以采用XML报文的方法,XML报文其实可以采用树的数据结构来存储,每个节点采用键值对来表示,这种方式很灵活。
DP_Krobelus 2013-11-02
  • 打赏
  • 举报
回复
绿色注释部分可以考虑变参函数
Arnis1973 2013-11-02
  • 打赏
  • 举报
回复
每个子类需要的数据类型都不一样, 设计用工厂模式, CMessageFacetory CConcertMessage
pathletboy 2013-11-02
  • 打赏
  • 举报
回复
派生类重载GenerateMsg函数实现。

64,633

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧