结构体编码转换中碰到的问题

使用环境:

在网络通信中,使用结构体进行通信

结构体定义如下:

客户端(采用utf-16编码):

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct MsgHead
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public char[] cSenderName;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public char[] cRecverName;
    };

服务器端(Linux系统,采用utf-8编码):

typedef struct _MsgHead  
{  
    char cSenderName[16];  
    char cRecverName[16];  
}MsgHead, *pMsgHead;

使用iconv()函数族进行utf-16到utf-8的代码转换

代码如下:

pMsgHead convertToMsgHead(char * recvBuf, int nRecv)
{
    CCodeConverter cv=CCodeConverter("utf-16", "utf-8");

    //一个占2byte的utf-16字符在utf-8中最多用4byte    
    int nTransBufSize=2*nRecv;
    //作为转换的中介
    char * transBuf=new char[nTransBufSize];
    memset(transBuf, 0, nTransBufSize);

    int nRet=cv.convert(recvBuf, nRecv, transBuf, nTransBufSize);
    if(nRet<0)
    {
        cv.getErrInfo();
        return NULL;
    }

    pMsgHead msgHead;
    memcpy(msgHead->cSenderName, transBuf, 16);
    memcpy(msgHead->cRecverName, transBuf+16, 16);
    
    //释放转换中介缓存
    delete(transBuf);
    return msgHead;
}
出现问题:

即将接收到的结构体整体转换过去,但是发现会导致接收的时候紊乱

调试代码,如下所示:

utf-16

0

2

4

6

8

10

12

14

16

18

20

22

24

26

28

30

32

34

0

0

0

0

0

0

0

0

0

0

0

0

0

0

s

e

utf-8

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

0

0

0

0

0

0

0

0

0

0

0

0

0

0

s


注意:

汉字在utf-16中占2个byte,但在utf-8中占3个byte

问题解析:

把接收到的前4个byte的汉字转换成6个byte之后,其后的28个0,转换为utf-8中的14个0

这样, 导致了接收的时候无法合理的进行转换

解决办法:

逐字段的进行编码转换

代码如下:

pMsgHead convertToMsgHead(char * recvBuf, int nRecv)
{
    CCodeConverter cv=CCodeConverter("utf-16", "utf-8");

    //一个占2byte的utf-16字符在utf-8中最多用4byte    
    int nTransBufSize=2*nRecv;
    //作为转换的中介
    char * transBuf=new char[nTransBufSize];
    memset(transBuf, 0, nTransBufSize);

    pMsgHead msgHead;
    //转换字段cSenderName
    cv.convert(recvBuf, 32, transBuf, nTransBufSize);    
    memcpy(msgHead->cSenderName, transBuf, 16);
    //转换字段cRecverName
    cv.convert(recvBuf+32, 32, transBuf, nTransBufSize);
    memcpy(msgHead->cRecverName, transBuf+16, 16);
    
    //释放转换中介缓存
    delete(transBuf);
    return msgHead;
}

小结:

碰到不同编码的应用程序之间通信,而且有消息格式的限制时,最容易出现这种问题

在发送的时候也会出现类似的问题

因此,需要创建一个符合规范的发送结构体来对从utf-8要发送到utf-16客户端的消息进行规范

发送时的转换:

需要用到的匹配结构体:

typedef struct _CommMsgHead  
{  
    char cSenderName[32];  
    char cRecverName[32];  
}CommMsgHead, *pCommMsgHead;
转换代码则与接收时的转换类似,需要逐字段进行编码转换

你可能感兴趣的:(结构体编码转换中碰到的问题)