在网络中传输结构体时,需要注意以下两点:
(1)要消除间隙,避免CPU字长不一样,造成错位;
(2)要转换字节序,避免cpu字节序不一样造成错误。
可以通过以下方式封装解封装消息。
xx_msg.h
#ifndef XX_MSG_H
#define XX_MSG_H
#define XX_MSG_HDR_LEN 8 /* 消息头部长度,包括type字段和length字段 */
#define XX_MAX_MSG_LEN 1024 /* 最大消息长度,只包括value字段*/
#define XX_MSG_ENCAP_8BIT(pbuff, value, encapLen) \
do \
{ \
unsigned char netSeqVal = 0; \
\
netSeqVal = (value); \
memcpy(pbuff, &netSeqVal, 1); \
\
(pbuff) += 1; \
(encapLen) += 1; \
} \
while(0)
#define XX_MSG_ENCAP_16BIT(pbuff, value, encapLen) \
do \
{ \
unsigned short netSeqVal = 0; \
\
netSeqVal = htons(value); \
memcpy(pbuff, &netSeqVal, 2); \
\
(pbuff) += 2; \
(encapLen) += 2; \
} \
while(0)
#define XX_MSG_ENCAP_32BIT(pbuff, value, encapLen) \
do \
{ \
unsigned int netSeqVal = 0; \
\
netSeqVal = htonl(value); \
memcpy(pbuff, &netSeqVal, 4); \
\
(pbuff) += 4; \
(encapLen) += 4; \
} \
while(0)
#define XX_MSG_ENCAP_STR(pbuff, pStr, strLen, encapLen) \
do \
{ \
memcpy(pbuff, pStr, strLen); \
\
(pbuff) += strLen; \
(encapLen) += strLen; \
} \
while(0)
#define XX_MSG_DECAP_8BIT(pbuff, value, decapLen) \
do \
{ \
unsigned char netSeqVal = 0; \
\
memcpy(&netSeqVal, pbuff, 1); \
(value) = netSeqVal; \
\
(pbuff) += 1; \
(decapLen) += 1; \
} \
while(0)
#define XX_MSG_DECAP_16BIT(pbuff, value, decapLen) \
do \
{ \
unsigned short netSeqVal = 0; \
\
memcpy(&netSeqVal, pbuff, 2); \
(value) = ntohs(netSeqVal); \
\
(pbuff) += 2; \
(decapLen) += 2; \
} \
while(0)
#define XX_MSG_DECAP_32BIT(pbuff, value, decapLen) \
do \
{ \
unsigned int netSeqVal = 0; \
\
memcpy(&netSeqVal, pbuff, 4); \
(value) = ntohl(netSeqVal); \
\
(pbuff) += 4; \
(decapLen) += 4; \
} \
while(0)
#define XX_MSG_DECAP_STR(pbuff, pStr, strLen, decapLen) \
do \
{ \
memcpy(pStr, pbuff, strLen); \
\
(pbuff) += strLen; \
(decapLen) += strLen; \
} \
while(0)
typedef int (*XX_ENCAP_MSG_FUNC_P)(unsigned char *pBuff, void *pMsg);
typedef int (*XX_DECAP_MSG_FUNC_P)(unsigned char *pBuff, void *pMsg);
typedef enum xxMsgType
{
XX_MSG_TYPE_A,
XX_MSG_TYPE_B,
XX_MSG_TYPE_C,
XX_MSG_TYPE_D,
XX_MSG_TYPE_CNT,
}XX_MSG_TYPE_E;
typedef struct xxIpAddr
{
int af;
union
{
struct in_addr ipv4Addr;
struct in6_addr ipv6Addr;
}u;
}XX_IP_ADDR_S;
typedef struct xxAMsg
{
XX_IP_ADDR_S addr;
unsigned int a;
unsigned short b;
char c[40];
}XX_A_MSG_S;
extern int xx_EncapAMsg(unsigned char *pBuff, XX_A_MSG_S *pAMsg);
extern int xx_DecapAMsg(unsigned char *pBuff, XX_A_MSG_S *pAMsg);
extern int xx_EncapMsg(unsigned char *pBuff, int msgType, void *pMsg);
extern int xx_DecapMsg(unsigned char *pBuff, int msgType, void *pMsg);
extern int xx_EncapPkt(unsigned char *pBuff, int msgType, unsigned int msgLen, unsigned char *pMsgVal);
extern int xx_DecapPkt(unsigned char *pBuff, int *pMsgType, unsigned int *pMsgLen, unsigned char *pMsgVal);
#endif
xx_msg.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
XX_ENCAP_MSG_FUNC_P gXxEncapMsgFuncTbl[XX_MSG_TYPE_CNT] =
{
(XX_ENCAP_MSG_FUNC_P)xx_encapAMsg,
(XX_ENCAP_MSG_FUNC_P)xx_encapBMsg,
(XX_ENCAP_MSG_FUNC_P)xx_encapCMsg,
(XX_ENCAP_MSG_FUNC_P)xx_encapDMsg,
}
XX_DECAP_MSG_FUNC_P gDecapMsgFuncTbl[XX_MSG_TYPE_CNT] =
{
(XX_DECAP_MSG_FUNC_P)xx_decapAMsg,
(XX_DECAP_MSG_FUNC_P)xx_decapBMsg,
(XX_DECAP_MSG_FUNC_P)xx_decapCMsg,
(XX_DECAP_MSG_FUNC_P)xx_decapDMsg,
}
int xx_EncapAMsg(unsigned char *pBuff, XX_A_MSG_S *pAMsg)
{
unsigned int encapLen = 0;
assert(pBuff != null);
assert(pAMsg!= null);
XX_MSG_ENCAP_32BIT(pBuff, pAMsg->addr.af, encapLen);
if (pAMsg->addr.af == AF_INET)
{
XX_MSG_ENCAP_32BIT(pBuff, pAMsg->addr.u.ipv4Addr.s_addr, encapLen);
}
else
{
XX_MSG_ENCAP_STR(pBuff, &pAMsg->addr.u.ipv6Addr, sizeof(pAMsg->addr.u.ipv6Addr), encapLen);
}
XX_MSG_ENCAP_32BIT(pBuff, pAMsg->a, encapLen);
XX_MSG_ENCAP_16BIT(pBuff, pAMsg->b, encapLen);
XX_MSG_ENCAP_STR(pBuff, pAMsg->c, sizeof(pAMsg->c), encapLen);
return encapLen;
}
int xx_DecapAMsg(unsigned char *pBuff, XX_A_MSG_S *pAMsg)
{
unsigned int encapLen = 0;
assert(pBuff != null);
assert(pAMsg != null);
XX_MSG_DECAP_32BIT(pBuff, pAMsg->addr.af, encapLen);
if (pAMsg->addr.af == AF_INET)
{
XX_MSG_DECAP_32BIT(pBuff, pAMsg->addr.u.ipv4Addr.s_addr, encapLen);
}
else
{
XX_MSG_DECAP_STR(pBuff, &pAMsg->addr.u.ipv6Addr, sizeof(pAMsg->addr.u.ipv6Addr), encapLen);
}
XX_MSG_DECAP_32BIT(pBuff, pAMsg->a, encapLen);
XX_MSG_DECAP_16BIT(pBuff, pAMsg->b, encapLen);
XX_MSG_DECAP_STR(pBuff, pAMsg->c, sizeof(pAMsg->c), encapLen);
return encapLen;
}
int xx_EncapMsg(unsigned char *pBuff, int msgType, void *pMsg)
{
unsigned int encapLen = 0;
assert(pBuff != null);
assert(msgType >= 0);
assert(msgType < XX_MSG_TYPE_CNT);
assert(pMsg != null);
assert(gXxEncapMsgFuncTbl[msgType] != null);
encapLen = gXxEncapMsgFuncTbl[msgType](pBuff, pMsg);
return encapLen;
}
int xx_DecapMsg(unsigned char *pBuff, int msgType, void *pMsg)
{
unsigned int encapLen = 0;
assert(pBuff != null);
assert(msgType >= 0);
assert(msgType < XX_MSG_TYPE_CNT);
assert(pMsg != null);
assert(gXxDecapMsgFuncTbl[msgType] != null);
encapLen = gXxDecapMsgFuncTbl[msgType](pBuff, pMsg);
return encapLen;
}
int xx_EncapPkt(unsigned char *pBuff, int msgType, unsigned int msgLen, unsigned char *pMsgVal)
{
unsigned int encapLen = 0;
assert(pBuff != null);
assert(msgType >= 0);
assert(msgType < XX_MSG_TYPE_CNT);
assert(msgLen < XX_MAX_MSG_LEN);
assert(pMsgVal != null);
XX_MSG_ENCAP_32BIT(pBuff, msgType, encapLen);
XX_MSG_ENCAP_32BIT(pBuff, msgLen, encapLen);
XX_MSG_ENCAP_STR(pBuff, pMsgVal, msgLen, encapLen);
return encapLen;
}
int xx_DecapPkt(unsigned char *pBuff, int *pMsgType, unsigned int *pMsgLen, unsigned char *pMsgVal)
{
unsigned int decapLen = 0;
assert(pBuff != null);
assert(pMsgType!= null);
assert(pMsgLen!= null);
assert(pMsgVal != null);
XX_MSG_DECAP_32BIT(pBuff, *pMsgType, decapLen);
XX_MSG_DECAP_32BIT(pBuff, *pMsgLen, decapLen);
XX_MSG_DECAP_STR(pBuff, pMsgVal, *pMsgLen, decapLen);
return decapLen;
}