【问题标题】:fill structure in socket插座中的填充结构
【发布时间】:2013-11-09 20:24:47
【问题描述】:

我想在 Windows 套接字中发送结构。我使用 TCP 协议。

例如我有这个结构:

typedef struct  headerLobby
{
    unsigned      nbGames;
}    head; 

我发送我的结构:

char buff[DEFAULT_BUFFER_LENGTH]; //DEFAULT_BUFFER_LENGTH = 512
headerLobby header;

header.nbGames = 1;
memcpy(buff, &header,  sizeof(headerLobby));
send(ClientSocket, buff, sizeof(headerLobby, 0);

我收到数据:

headerLobby header;

char recvbuf[DEFAULT_BUFFER_LENGTH];
memset(recvbuf, 0, DEFAULT_BUFFER_LENGTH);
int iResult = recv(ConnectSocket, recvbuf, DEFAULT_BUFFER_LENGTH, 0);

memcpy(&header,recvbuf,  sizeof(headerLobby));

但是当我打印 header.nbrGames 时,我没有很好的价值。

客户端和服务器都在 windows 8 64 位和处理器 intel x64 中。 我不明白我的代码有什么问题。

【问题讨论】:

  • 您将 memcpying 数据从未初始化的 buff 转换为 header,而不是相反。
  • @AdamLiss - 这应该是一个答案而不是评论
  • @Adam Liss - 抱歉,我在示例代码中取反了值。我编辑我的帖子。
  • 你能打印/检查 send() 和 recv() 的返回值吗?

标签: c sockets tcp structure


【解决方案1】:

您能否转储您尝试发送并且正在接收的十六进制数据。使用wireshark/类似工具在发送/接收端进行数据包捕获,并查看您在网络上看到的数据包数据是您所期望的。

几个最佳实践,

  1. 始终保持结构大小一致。如有必要,在结构末尾使用填充。如果您不这样做,编译器将自动保持结构大小对齐,这将导致您在线发送的数据可能与您尝试发送的数据不匹配。

  2. 在通过网络发送任何内容之前,请按照网络字节顺序保存数据。您可以使用 htonl 进行转换。它可能不会在这里引起问题,因为拱门是相同的并且您正在处理数据等。但这可能会导致可移植代码出现问题。

【讨论】:

  • 如果您打算使用 htonl 来解决字节序问题,请务必同时提及由 atomic element size的差异引起的问题的可能性> 从一台机器到另一台机器。 (请参阅链接页面下方的 2/3)
  • @joe - 我看到 htonl 存在于 unix 和 windows 上,那么为什么它可能会导致可移植代码出现问题?
  • @Bob 我不是说 htonl 可能会导致问题。我是说,如果您在发送字节之前不执行 htonl,则可能会导致问题。但在您的情况下,网络顺序转换可能不是导致问题的原因,因为您说源和目标使用相同的架构、相同的操作系统等。抱歉造成混淆。顺便说一句,你搞定了吗?
【解决方案2】:
  (...)
  header.nbGames = 1;
  memcpy(buff, &header, sizeof(struct headerLobby));
  send(ClientSocket, buff, sizeof(struct headerLobby), 0);

  memset(recvbuf, 0, 20);
  int iResult = recv(ConnectSocket, recvbuf, 20, 0);
  memcpy(&recvheader, recvbuf, sizeof(struct headerLobby));

  printf("%d\n", recvheader.nbGames);
  (...)

$ ./out

1

所以,它有效。你的代码是正确的。或者您显然对其进行了编辑以将其粘贴到此处,从而删除了有问题的部分。提示:总是创建一个最小的测试用例来证明或反驳你的问题。

【讨论】:

  • 就是这样。我的问题不是第一个结构的 memcpy,而是当我有另一个结构时。当我发送两个结构时,我将指针发送到第二个结构而不是第一个..
【解决方案3】:

我发现了我的错误。示例代码有效,但我的错误是我想发送几个结构。当我发送结构时,我没有将指针发送到第一个结构。

例如:

char buff[DEFAULT_BUFFER_LENGTH]; //DEFAULT_BUFFER_LENGTH = 512
headerLobby header;
GameInfo info; //other struct

header.nbGames = 1;
info.nbPlayers = 3;
memcpy(buff, &header,  sizeof(headerLobby));
buf += sizeof(headerLobby);
memcpy(buf, &info, sizeof(gameInfo));
send(ClientSocket, buff, sizeof(headerLobby, 0); //I lost the pointeur to the first struct

【讨论】:

    【解决方案4】:

    虽然可以安全地完成,但通过套接字(或为此使用任何二进制方法)发送结构数据是有风险的,原因有几个。

    内在类型的大小可能因机器而异。
    发送机器上的填充接收机器上可能不同。
    发送机器上的字节序规则可能与接收机器上不同。

    从一开始就以这种方式发送结构数据通常不是一个好主意,有一个警告

    如果您先将数据序列化到缓冲区中 (credit to this post),这些问题就会得到解决。

    【讨论】:

      猜你喜欢
      • 2011-08-13
      • 2023-04-03
      • 2016-10-28
      • 2015-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-27
      相关资源
      最近更新 更多