2

我有一个客户端和服务器程序,我想从客户端发送整个结构,然后在服务器上输出结构成员“ID”。

我已经完成了所有的连接等操作,并且已经设法通过以下方式发送了一个字符串:

send(socket, string, string_size, 0);

那么,是否可以通过 send() 发送结构而不是字符串?我可以将服务器上的缓冲区替换为相同类型的空结构并继续吗?

4

7 回答 7

4

客户端和服务器机器“相同”吗?只有在每一端的 C 编译器在内存中布局完全相同的结构时,您所提议的内容才会起作用。有很多原因可能不是这种情况。例如,客户端和服务器机器可能具有不同的架构,那么它们在内存中表示数字的方式(大端、小端)可能会有所不同。即使客户端机器和服务器机器具有相同的架构,两个不同的 C 编译器也可能对它们在内存中布局结构的方式有不同的策略(例如,在字段之间填充以对齐字边界上的整数)。即使是具有不同标志的同一个编译器也可能给出不同的结果。

务实地说,我猜你的客户端和服务器是同一种机器,所以你提议的东西会起作用,但是你需要知道,作为一般规则它不会,这就是为什么像 CORBA 这样的标准被发明,或者为什么人们使用一些通用的表示,例如 XML。

于 2009-11-14T17:11:00.143 回答
2

如果客户端和服务器以完全相同的方式布置结构,则您可以,这意味着字段的大小都相同,具有相同的填充。例如,如果您long的结构中有一个,那么在一台机器上可能是 32 位,而在另一台机器上可能是 64 位,在这种情况下,将无法正确接收该结构。

在您的情况下,如果客户端和服务器总是使用非常相似的 C 实现(例如,如果这只是您用来学习一些基本概念的代码,或者由于某些其他原因您知道您的代码只会曾经必须在您当前版本的 OSX 上运行),那么您可能可以摆脱它。请记住,您的代码不一定能在其他平台上正常工作,并且在它适用于大多数实际情况之前还有更多工作要做。

对于大多数客户端-服务器应用程序,这意味着答案是您通常不能这样做。您实际上所做的是根据发送的字节数、顺序、含义等来定义消息。然后在每一端,您都执行特定于平台的操作,以确保您使用的结构具有完全所需的布局。即便如此,如果您要发送 struct little-endian 的整数成员,您可能必须进行一些字节交换,然后您希望您的代码在 big-endian 机器上运行。存在 XML、json 和 Google 的协议缓冲区等数据交换格式,因此您不必做这些繁琐的事情。

[编辑:当然还要记住,某些结构成员永远不能通过网络发送。例如,如果您的结构中有一个指针,那么该地址指的是发送机器上的内存,而在接收端是无用的。抱歉,如果这对您来说已经很明显,但是当他们刚开始使用 C 时,这对每个人来说肯定不是显而易见的]。

于 2009-11-14T17:11:15.040 回答
2

嗯......如果你做得正确,通过网络发送结构有点困难。

Carl 是对的——你可以通过网络发送一个结构体:

send(socket, (char*)my_struct, sizeof(my_struct), 0);

但事情是这样的:

  • sizeof(my_struct) 可能会在客户端和服务器之间发生变化。编译器通常会进行一些填充和对齐,因此除非您明确定义对齐方式(可能使用#pragma pack()),否则该大小可能会有所不同。
  • 另一个问题往往是字节顺序。有些机器是大端的,有些机器是小端的,所以字节的排列可能不同。实际上,除非您的服务器或客户端在非英特尔硬件上运行(可能并非如此),否则这个问题在理论上比在实践中更存在。

所以人们经常提出的解决方案是有一个序列化结构的例程。也就是说,它一次向 struct 发送一个数据成员,确保客户端和服务器仅 send() 和 recv() 您在程序中编码的确切指定字节数。

于 2009-11-14T17:16:07.840 回答
1

你可以,但你需要注意两件重要的事情。

  1. 两端的程序必须与ABI兼容。如果两端都运行在相同的处理器架构、相同的操作系统、使用相同的编译器和编译器标志编译,它们通常是这样的。
  2. TCP是一个流。您必须确保发送整个结构。查看 send() 调用的文档 - 它返回发送的字节数 - 这可能比您告诉它的要少。接收端也一样。仅仅因为您通过 1 个 send 调用发送了该结构,并不意味着您将通过 1 个 recv 调用收到它。需要几次 recv 调用才能获得所有部分。
于 2009-11-14T17:17:32.610 回答
0

是的,相同类型的结构都具有相同的大小。如果你的指针投射正确,你就可以开始了。

于 2009-11-14T17:00:03.050 回答
0

一般来说,这样做是个坏主意,即使您的客户端和服务器最终以相同的方式在内存中布置结构。

即使您不打算来回传递更复杂的数据结构(可能涉及指针),我也建议您在通过网络发送数据之前对数据进行序列化。

于 2009-11-14T17:22:04.067 回答
-3

将数据作为文本文件发送,然后在接收后解码。如果您希望发送数据,这是最好的方法!

于 2010-01-26T20:30:56.533 回答