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

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

send(socket, string, string_size, 0);

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

有帮助吗?

解决方案

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

卡尔是对的 - 你可以通过网络发送一个结构:

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

但事情是这样的:

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

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

其他提示

在客户端和服务器计算机“一样”?你有什么提议,如果在每一端的C编译器在内存布局结构完全一样只会工作。有很多的原因,这可能并非如此。例如,客户端和服务器macines可能有不同的架构,那么他们的方式代表了内存中的号码(大端,小端)可能会有所不同。即使客户机和服务器计算机具有相同结构的两个不同的C编译器可能对他们是如何布置在存储器结构不同的策略(如字段之间填充对齐的字边界整数)。甚至在相同 conmpiler具有不同标志可能得到不同的结果。

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

可以,如果客户端和服务器奠定了结构完全相同的方式,这意味着字段大小相同,具有相同的填充。例如,如果你在你的结构一个long,这可能是对其他一台机器上32位和64位,在这种情况下,结构将不会被正确接收。

在你的情况,如果客户端和服务器总是要上非常类似C语言实现(例如,如果这只是你用来学习一些基本的概念代码,或者其他一些原因,你知道你的代码仅会以您目前的OSX版本上运行),那么你也许可以逃脱它。只要记住,你的代码不一定正确在其他平台上工作,而且还有更多的工作要做这是适用于大多数现实世界的情况下才可使用。

对于大多数客户端 - 服务器应用程序,这意味着,答案是,你不能这样做一般。你真正要做的是发送的字节数,什么样的顺序来定义的消息,他们的意思是什么,等等。然后,在每端,你做平台,具体的事情,以确保您使用的结构有准确所需的布局。即便如此,你可能有,如果你要发送的结构小端的整数成员做一些字节交换,然后你想你的代码大端机器上运行。数据交换格式,如XML,JSON和谷歌的协议缓冲区存在,这样你就不必做这个繁琐的东西。

[编辑:还记得当然,一些结构成员可以从不通过导线发送的。例如,如果你的结构中有一个指针,那么地址是指在发送机器上的内存,并且是在接收端没用。道歉,如果这已经是明显的给你,但它肯定是不有目共睹的时候,他们只是用C]开始。

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

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

是的,相同类型的结构都具有相同的尺寸。如果你得到你的指针铸造的权利,你是好去。

在一般情况下,这是一个坏主意,要做到这一点,即使你的客户端和服务器变成奠定了存储器中的结构相同的方式。

即使你不打算通过更复杂的数据结构(这将涉及指针)来回,我建议你系列化你的数据,你通过网络发送之前。

发送的数据作为文本文件,然后收到后对其进行解码。这是最好的方式,如果你希望你的数据作为其SENT !!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top