网络数据传输格式 (转CSDN 贴)

xml有良好的开放性、可读性和可扩充性。如果你的协议是开放的,并且希望别人也能帮你做些扩充功能的什么插件的,可以考虑用xml。但是最本质的一点,xml的有效载荷实在太低,封装和解析效率太低,所以只适用于非常少量,对性能没要求的网络流量。典型的案例就是文字聊天。如 GTalk 的基础,开源的即时消息协议系统 Jabber。

另外,对于java和.net系统,由于内置xml引擎,采用xml有天然的优势。而且反正这么累赘了,也不在乎xml的流量再多耗费点。
但是对于c++, xml显然就太累赘了。最重要的是,如果你的工程中本身没有xml需求,那么还需要额外的引入一个xml引擎,无论是从速度、效率、可靠性、代码复杂性来看,都非常的得不偿失。

c++的网络处理,千变万化,但离不了的一个宗旨,就是:

C++形式的易读易懂易访问的结构形式  <=序列化=> 无类型的缓冲区数据。

C++的结构体按照需求随便定义,缓冲区就是一段字节数据,各种技巧大部分集中在序列化的操作上。一般的应用级别,在结构体前面加上 类型识别,长度确定就可以。而对性能和带宽要求苛刻的应用,可能会将结构体拆解,并按照位类序列号,以最大限度的节约带宽,典型的例子是diablo的封包。

对于一般的应用,序列化通常是    类型 | 长度 | 原始结构体
或者调换下  长度  |  类型  |  原始结构体

这种形式接单可靠而且足够用,但是有几个小技巧,可以提升下性能和简化下操作流程。
因为需要在原始结构体前面加入两个数据,因此序列化时需要拷贝内容到缓冲区,拷贝操作本身会浪费些些的时钟周期和内存,虽然不多,但是频繁操作的话,也是种累赘。有两种方式可以避免这种拷贝操作。

方法一: 将类型和长度定义到结构体里面,如:
struct BaseMsg{
BYTE type;
BYTE len;
};
所有的结构均继承自BaseMsg,就可以整个结构一次发送了,发送的流程也很简单。
SendMsg(BaseMsg* pMsg)
{
  Send(pMsg, pMsg->len);
}

方法二:利用集散IO的功能。集散IO可以同时发送(接受)多个不同的部分。这样子就不必拷贝了。如:
BYTE header[4];
BYTE* pMsg = 要发送的结构体;

WSABUF buff[2];
buff[0] = header;
buff[1] = pMsg;

WSASend(buff, 2, ......)

出处:http://topic.csdn.net/u/20090514/18/17cab6cd-cd50-4c77-9629-db16b11dc1f2.html?35230

你可能感兴趣的:(csdn)