在插座中填充结构

时间:2013-11-08 23:41:33

标签: c sockets tcp structure

我想在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中。 我不明白我的代码中有什么问题。

4 个答案:

答案 0 :(得分:1)

您可以转储您尝试发送的十六进制数据吗?使用wireshark /类似工具在发送/接收端进行数据包捕获,并查看您在线路上看到的数据包数据是您所期望的。

几乎没有最佳做法,

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

  2. 在线路上发送任何内容之前,请按网络字节顺序保存数据。您可以使用htonl进行转换。它可能不会导致这里的问题,因为arch是相同的,你正在处理数据等。但它可能会导致可移植代码中的问题。

答案 1 :(得分:0)

  (...)
  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

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

答案 2 :(得分:0)

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

例如:

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

答案 3 :(得分:-1)

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

内在类型的尺寸 可能因机器而异。
发送计算机上 填充 在接收计算机上可能有所不同 发送计算机上的 endian规则 可能与接收计算机上的不同。

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

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