C#端和C++端套接字通信中的几个问题

来源:互联网 发布:淘宝怎么看物流信息 编辑:程序博客网 时间:2024/06/05 02:34

(1) 从字符串转为固定大小的字符数组

如:定义固定大小的结构体:

(使用命名空间:using System.Runtime.InteropServices;)

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]    struct OnlineUsrInfo    {        [MarshalAs(UnmanagedType.ByValArray, SizeConst=16)]        public char[] name;        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]        public char[] IP;        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]        public char[] port;    }
将string转为char[]时,需要用string对象的PadRight()方法来填充一定大小的字符数组

OnlineUsrInfo.name=str.PadRight(16);

这个方法有一个弊端,就是在name中,内存部分内容为空格,如果传递给C++程序使用,会因为没有字符串终结符“\0”而一直把结构体中的字符读完,从而导致出错

故,一般用PadRight()方法的重载函数 PadRight(16, '\0'); 来实现

注意:最好用PadRight(int nWidth, '\0'); 来填充,否则会默认以空格(space=32)来填充;

(2)从字符数组转为字符串时的问题

同样,从C++端传过来的字符数组,会内存初始化为0,即‘\0’

如接收到的字符数组内容为:"xuwei\0\0\0\0\0\0\0\0\0\0\0"

将该字符数组转为字符串时,会将之后的'\0'都算到字符串内

因此,如何把字符串中的 '\0' 去掉也是一个问题

想到的方法有两个:

(一)用string对象的Trim()方法,即Trim('\0'),去掉所有的'\0'字符

(二)用string对象的Replace()方法,即Replace('\0', ''),用空格去代替‘\0’  字符串会自动过滤掉空格

(3) 关于结束符的问题

C# 字符串末尾没有以 null('0')结尾的字符;而在C++中,字符串末尾以null('\0')结束

因此,在传输时,要注意字符串的处理

1> 从C#端传输到C++端:

例如,发送"hello",5个char

由于C++端不知道结束符,所以可能收到"hello]"之类的错误;即会有乱码

因此,在C++端接收时,应该将收到的字符再处理一下;

2> 从C++端传输到C#端

例如,发送"hello",5个char(占5Byte)

如果只是发送5个字节,则接收端可能会收到104  101 108 108 108,即"helll";

如果发送6个字节,接收端以为接收到6个char,最后可能会收到104 101 108 108 111 111,即"helloo";(最后一个为乱码)

因此,最后选择的办法是:发送6byte,但通知接收端只有5个char

(4)不同平台的编码方式的转换

C#端使用的是utf-16编码方式;Linux中C++使用的是utf-8编码方式;Windows中C++使用的是ANSI编码方式;

因此,在转换的时候要转换成通用的编码,如utf-16

Linux中可以用iconv()函数族进行utf-8->utf-16的编码转换;

Windows中可以用mbstowcs()/MultiByteToWideChar()等函数来进行ANSI->utf-16的编码转换

(5)关于中文的转换

英文的话,一个utf-16码(一个char)转换为一个utf-8码(一个char);

但中文的话,一个utf-16(一个char)转换成了三个utf-8码(三个char);

因此,C#发送中文给C++发送中文时,需要告诉客户端需要处理多少char

C#端可通过UnicodeEncoding.UTF8.GetByteCount(data); 来获取data转换成utf-8之后的char个数,以便接收端进行处理

补充的几个知识点:

1> C#可用Encoding.Default.EncodingName来输出默认的编码名

原创粉丝点击