使用环境:
在网络通信中,使用结构体进行通信
结构体定义如下:
客户端(采用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;
代码如下:
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;转换代码则与接收时的转换类似,需要逐字段进行编码转换