嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

周梦康 发表于 2015-12-07 2832 次浏览 标签 : CYar

免费领取阿里云优惠券 我的直播 - 《PHP 进阶之路》

yar-c中:https://github.com/laruence/yar-c/blob/master/yar_protocol.h

typedef struct _yar_header {    
    unsigned int   id;    
    unsigned short version;    
    unsigned int   magic_num;    
    unsigned int   reserved;    
    unsigned char  provider[32];    
    unsigned char  token[32];    
    unsigned int   body_len;    
} __attribute__ ((packed)) yar_header;

yar中:https://github.com/laruence/yar/blob/master/yar_protocol.h

#ifdef PHP_WIN32    
#pragma pack(push)    
#pragma pack(1)    
#endif    
typedef struct _yar_header {    
    unsigned int   id;    
    unsigned short version;    
    unsigned int   magic_num;    
    unsigned int   reserved;    
    unsigned char  provider[32];    
    unsigned char  token[32];    
    unsigned int   body_len;    
}    
#ifndef PHP_WIN32    
__attribute__ ((packed))    
#endif    
yar_header_t;    
#ifdef PHP_WIN32    
#pragma pack(pop)    
#endif

#pragma pack(1) 变量对齐在每个系统中是不一样的,默认的对齐方式能有效的提高cpu取指取数的速度,但是可能会浪费一定的空间。在网络程序中采用#pragma pack(1),即变量紧缩,不但可以减少网络流量,还可以兼容各种系统,不会因为系统对齐方式不同而导致解包错误。http://www.cppblog.com/range/archive/2011/07/15/151094.html

_attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。http://blog.chinaunix.net/uid-25768133-id-3485479.html

如果不是紧凑型,那么在win平台上会以结构体中最长的字节数据结构的长度对其,而在linux中会以int对其,所以这里虽然有一个short,但是默认与int一对其,整个长度就增加了2,如果当前结构体中有dobule类型,那么在win平台上占的空间更大。这样多个平台对其标准不一样,那么跨平台解析的时候也会出问题。

同时呢,正因为设置为紧凑型,使得我们在网络传递的时候方便直接以二进制流的形式传递,跨语言也变得毫无障碍。比如在java端可以直接写成

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(byteArrayOutputStream);

YarHeader yarHeader = yarRequest.getYarHeader();

try {
    out.writeInt(yarHeader.getId());
    out.writeShort(yarHeader.getVersion());
    out.writeInt(yarHeader.getMagicNum());
    out.writeInt(yarHeader.getReserved());

    for (char aProvider : yarHeader.getProvider()) {
        out.writeChar(aProvider);
    }

    for (char aToken : yarHeader.getToken()) {
        out.writeChar(aToken);
    }

    out.writeInt(yarHeader.getBodyLen());
    return byteArrayOutputStream.toByteArray();
} finally {
    byteArrayOutputStream.close();
    out.close();
}

这样服务端用 C 解析起来也没有问题了。

嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

评论列表