最近在写一个短信下发功能,客户端使用c#和java的短信网关的进行网络通信。
之前使用java进行开发,一切正常,改用c#无法收到网关应答。
想了半天意识到是不是网络字节序问题,
java默认就是大端字节序,和网络字节序是一至的,所以不转换也不会有问题,
而c#在windows平台上是小端字节序。
网络发送字节流是按大端序发送,也就是从左到右发送,和c#的小端序相反,造成网关不能正常识别协议。
尝试c#中转换一下字节序,通信成功。
c#中字节序转换有两种方法。
非字串使用 System.BitConverter.GetBytes()方法,先读入字节数组中,然后再用Array.Reverse()对byte数组反序一下,得到大端序字节数组。
代码:
short x = 6;
byte[] a=System.BitConverter.GetBytes(x); //得到小端字节序数组
Array.Reverse(a); //反转数组转成大端。
另外c#直接提供了网络字节序转换方法。
System.Net.IPAddress.HostToNetworkOrder(本机到网络转换)
System.Net.IPAddress.NetworkToHostOrder(网络字节转成本机)
推荐使用这种方法,简单有效。
代码示例:
short x = 6;
short b = System.Net.IPAddress.HostToNetworkOrder(x); //把x转成相应的大端字节数
byte[] bb = System.BitConverter.GetBytes(b);//这样直接取到的就是大端字节序字节数组。
对于字符串型:使用 System.Text.Encoding.Default.GetBytes();直接取字串对应字节数组。
不知道为什么这个方法取到的直接就是大端字节数组。不用转换。
后来查了一下,关于字串的字节序问题,因为gbk和utf-8都是以单个字节表示数字的,所以不存在字节序问题,在多个不同系统架构都用。对于utf-16,则是以双字节表示一个整数,所以为会有字节序问题,分大小端unicode。
System.Text.Encoding.Default.GetBytes();在我的简体中文系统上是以gb2312的编码,也就是单个字来进行编码的,所以也不会有字节序问题。
补充:“对于任何字符编码,编码单元的顺序是由编码方案指定的,与endian无关。例如GBK的编码单元是字节,用两个字节表示一个汉字。这两个字节的顺序是固定的,不受CPU字节序的影响。UTF-16的编码单元是word(双字节),word之间的顺序是编码方案指定的,word内部的字节排列才会受到endian的影响。”,所以utf-8也没有字节序的问题。字节序问题之存在于需要使用两个字节以上来表示整数。而UTF-8只是一串字节流,不存在字节序问题,不过将这些字节流翻译成Unicode比其他的传输方式复杂。以字节为单位编码的,无论一个汉字是多少个字节,都无字节序问题。
你注意,字节序问题不是指多个字节传输的先后,这个是固定的无异议的。而是指一个多字节编码在机器中的表示方式问题。
char str[] = "abaksdkakskasklasflk";这个无字节序问题。
但
int str[] = {0x11223344, 2, 3 }就有字节序问题了。因为str[0]同样数值不同机器中表示不同。
而剩下的, 就是字符编码内部的字节序了。比如UTF-16是用两个字节表示一个字符,但是这两个字节内部如何排序,系统并不知道,所以必须指定字节序。但是UTF-8由于几个字节表示并不相同,一定要从那个表示长度的字节开始读,相当于一开始就知道该从哪里是队头队尾,所以不存在字节序问题。
附上字节序说明:
为什么要注意字节序的问题呢?你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。但是,如果你的程序要跟别人的程序产生交互呢?尤其是当你把你在微机上运算的结果运用到计算机群上去的话。在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而JAVA编写的程序则唯一采用big endian方式来存储数据。试想,如果你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?就拿上面的 0x12345678来说,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了JAVA程序,由于JAVA采取big endian方式存储数据,很自然的它会将你的数据翻译为0x78563412。什么?竟然变成另外一个数字了?是的,就是这种后果。因此,在你的C程序传给JAVA程序之前有必要进行字节序的转换工作。
用文字说明可能比较抽象,下面用图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示:
Big Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 78 | 56 | 34 | 12 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
相关推荐
在C#中,处理字节数据可以使用`System.IO`命名空间中的`BinaryReader`类,它提供了一种方便的方式来读取二进制文件或流中的基本数据类型。不过,对于自定义的报文结构,我们需要自定义逻辑来按照码表解析数据。 ...
当通过C#进行串口通信时,由于串口接收缓冲区大小有限以及应用程序处理速度的影响,如果在短时间内有大量的数据涌入,很容易导致缓冲区溢出,从而造成数据丢失。此外,如果不恰当地处理数据读取和应用程序响应时间,...
总结起来,解决Java Socket与C#通信中中文乱码问题的关键在于: 1. **客户端**:确保使用`getBytes("UTF-8")`将字符串编码为UTF-8字节数组,然后通过Socket发送。 2. **服务器端**:在接收到数据后,使用`Encoding....
在IT领域,网络通信是核心部分之一,而C#中的Sockets则是实现客户端与服务端交互的重要工具。本文将深入探讨如何使用C# Sockets来构建一个简单的客户端和服务端通信模型,例如用户登录和发送/接收消息。 首先,我们...
字节流是.NET中处理数据的基本方式,`System.IO`命名空间提供了`Stream`类及其子类,如`NetworkStream`用于Socket通信。我们可以使用`StreamReader`和`StreamWriter`来读写字节流,或者直接使用`Read`/`Write`方法...
在C#中,`System.IO`命名空间下的`Stream`类及其子类如`FileStream`、`MemoryStream`等就是处理字节流的核心类。 图片文件,如JPG、PNG等,本质上是二进制数据,可以被转换为字节流进行处理。这个过程涉及到两个...
在C++中,可以使用`htonl`、`ntohl`等函数处理字节序转换,确保大端模式。 接下来是Java。Java提供了丰富的IO和NIO(New IO)库,如`InputStream`和`OutputStream`类用于字节流操作,`FileInputStream`和`...
- 为了提高性能和用户体验,服务器端通常会在一个单独的线程或异步任务中处理每个客户端连接,避免阻塞主线程。 - 使用`Task.Run()`或`BeginAcceptTcpClient()`等异步方法可以实现非阻塞的网络通信。 5. **安全性...
在Windows系统中,命名管道被广泛用于不同进程间的通信,尤其是跨语言的通信场景,如C#和C++。 在C#中,命名管道的实现主要依赖于`System.IO.Pipes`命名空间,其中`NamedPipeServerStream`和`NamedPipeClientStream...
Socket通信在IT行业中是网络编程的基础,特别是在C#这样的多平台开发环境中,Socket通信库的使用至关重要。本实例,"C# Socket通信稳定完整版类库实例",为我们提供了一个全面且稳定的解决方案,用于实现客户端与...
- `Socket`类是C#中处理TCP通信的基础,提供了诸如`Connect`、`Receive`、`Send`等方法。 - 使用`Socket.Receive`接收数据时,可能需要多次调用才能得到完整数据包,因为每次调用可能只返回部分数据。 4. **处理...
在C#编程中,串口通信(Serial Communication)是一种常用的技术,用于设备间的数据传输,如PC与PLC、传感器或其他电子设备之间的交互。本文将深入探讨如何在C#中进行串口通信,并解决中文传输时出现的乱码问题以及...
在C#编程中,通信是实现不同程序或设备间数据交换的关键部分。本文将探讨如何使用C#实现点对点(P2P)、点对多(multicast)、同步和异步通信,以及如何利用UDP和TCP这两种不同的传输协议。下面我们将深入理解这些...
在C#编程中,串口通信是一个非常重要的概念,尤其对于设备交互、数据传输和嵌入式系统等应用场景。`System.IO.Ports.SerialPort` 类是.NET Framework提供的一种方便的接口,用于处理串行端口通信。在这个项目中,...
本文将深入探讨如何在C#中实现Modbus RTU串口通信,包括封包格式、CRC校验计算以及测试工具的使用。 1. **Modbus RTU封包格式**: Modbus RTU消息结构包括以下部分: - 地址:1字节,表示接收或发送数据的设备...
在标题和描述中提到的“labview与c#进行通信”,主要涉及到的是跨平台、跨语言的数据交互,这里使用了Socket通信技术。 Socket,也称为网络套接字,是网络编程的基础,它提供了进程间通信(IPC)和网络通信的能力。...
总结来说,C#上位机开发中的串口通信主要包括配置串口参数、监听数据接收事件以及解析和处理接收到的16进制数据。理解这些概念并熟练应用,可以帮助我们构建能够读取和处理串口数据的高效上位机应用程序。通过不断...
在.NET框架中,C#为开发人员提供了丰富的网络通信库,包括TCP、UDP以及Socket通信。这些协议在软件开发中广泛应用于服务器与客户端之间的数据交换,尤其在分布式系统和实时应用中扮演着重要角色。本项目...
在跨语言通信或数据交换中,尤其是在涉及到C#与C++之间进行TCP通信时,由于两者数据表示方式的差异,可能会遇到将C#中的结构体转换为C++可理解的字节数组,或者反过来的过程。本文将详细介绍如何在C#中实现结构体与...
综上所述,C#中的串口通信涉及一系列配置、读写、事件处理和异常管理操作。通过深入理解这些知识点,并结合提供的源码,开发者可以快速掌握串口通信技术,应用于实际的项目开发中。在学习过程中,不断实践和调试,将...