Windows和Linux之间通过套接字进行通信的问题

时间:2019-02-04 16:42:46

标签: c linux windows sockets floating-point

我正在尝试通过Windows(客户端)和Linux(服务器)之间的套接字进行通信。我可以开始通信,但是在发送数据时会出现问题。 主要问题是我尝试发送2个数据double和1个ulong数据,但是当我在服务器(Linux)上读取它们时,无法读取正确的值。 例如,如果我发送double1 = 1.5,则我在服务器上收到0.0000。然后,如果我发送double1 = 550.0,则在服务器上收到-12382718421 ...(垃圾桶)

我尝试使用htonl,ntohl等。它不起作用 我试图重新排序我从客户端发送的帧的字节,即发送B0 ... B7而不是B7 ... B0...。它不起作用。 我一直在寻找有关它的信息,但是我什么也找不到,除了不同操作系统之间的套接字通信是可能的,因此我知道有解决方案。

我的问题是:

1-htonl和nthol仅适用于整数吗?我可以将这些转换用于浮动数据吗?

2-在Linux和Windows中,一帧的字节顺序是什么?

3-我知道sendto()函数返回正在发送的字节数。我发送的是20Bytes->(2 * 8Bytes(double)+ 1 * 4Bytes(ulong))= 20Bytes。但是函数返回24Bytes,这怎么可能?是由于UDP协议标头还是包含Windows的其他信息?

谢谢。

PD1:套接字的编程正确。

PD2:在Linux-Linux之间,我没有问题,我可以正确发送数据。

2 个答案:

答案 0 :(得分:2)

  

1-htonl和ntohl仅适用于整数吗?我可以将这些转换用于浮动数据吗?

这些函数仅针对整数定义。您需要知道每个平台存储双精度格式的格式(包括字节序),以决定是否需要重新排序字节或执行其他转换。

  

2-在Linux和Windows中,一帧的字节顺序是什么?

这个问题没有道理。您决定要在此数据包中放入什么,因此字节顺序就是您发送的内容。

传统上,wire格式通常是big-endian的,但是许多现代格式都是little-endian的,其理由是大多数同行将使用x86。

对于您的特定情况,在Linux上接收的事实与在Linux上运行的体系结构无关。您没有提到它,但是假设x86_64的字节序和double格式可能与您的发送代码相同。

NB。您可能应该使用<stdint.h>中的固定大小类型,例如使用uint64_t而不是unsigned long(假设这是您想要的)。甚至在同一平台上,long之类的类型在不同的ABI中也可以具有不同的大小。

  

3-我知道sendto()函数返回正在发送的字节数。我发送的是20Bytes->(2 * 8Bytes(double)+ 1 * 4Bytes(ulong))= 20Bytes。但是函数返回24Bytes,这怎么可能?是由于UDP协议标头还是包含Windows的其他信息?

显示您的代码。 sendto的返回值不应大于您传递的length参数,因此,该值可能不是您所想的。

额外的长度肯定不是IP或UDP标头,无论如何它们都长于4个字节。


  

我尝试使用htonl,ntohl等。它不起作用

尝试不同的转换时不要停下来,希望能奏效。

在发送之前打印缓冲区的十六进制转储。收据后打印缓冲区的十六进制转储。填写您希望在接收器中看到的结构,然后十六进制转储那个,这样您就可以看到区别。

答案 1 :(得分:0)

  

htonl和nthol仅适用于整数吗?我可以将这些转换用于浮动数据

要管理 float ,例如,您可以使用 union uint32_t中转换 float ,反之亦然,或者使用 float 的指针指向uint32_t cast ,反之亦然,当然,不将 float 投射到{ {1}}并反向

但是您似乎使用的是 double 而不是 float ,在这种情况下,您需要使用 htobe64 / htole64 / be64toh / le64toh uint32_t),如果未在Windows下定义它们,请确定数据包中的顺序或字节并自行定义转换

  

在Linux和Windows中,帧的字节顺序是什么

顺序仅取决于CPU,而不取决于OS

  

我知道sendto()函数返回正在发送的字节数。我发送的是20Bytes->(2 * 8Bytes(double)+ 1 * 4Bytes(ulong))= 20Bytes。但是函数返回24Bytes,这怎么可能?是由于UDP协议标头还是包含Windows的其他信息?

您只能访问有效载荷,所有页眉/页脚/等内容都对您隐藏了

可能您发送的是 struct 而不是让自己成为要发送的数据包,在这种情况下,编译器只是不遵循相同的填充,或者long的大小在32位上是32b,而在64位上是64b。其他?

请勿发送 struct ,将数字复制到管理字节序的字节向量中,然后以相同的方式提取它们


例如,手工完成一个 unsigned long 读写8个字节,即使它们在主机上的容量为64b,而在另一个主机上的容量较小,也可以兼容:

endian.h