【问题标题】:Server not receiving trailing longs in c++ socket服务器未在 C++ 套接字中接收尾随长
【发布时间】:2014-09-14 01:24:49
【问题描述】:

我正在使用 c++ 通过套接字传输结构。我阅读了一些关于发送结构的早期问题,建议的一种方法是在转换后使用 char* 进行传输。由于服务器和客户端都在同一台机器上,所以这里没有字节序问题。

这里有几个问题。我得到 struct 的大小为 48。根据我的计算,它不应该是 43 吗? 8x4 + 10 +1

其次,在服务器端,当我打印接收到的缓冲区时,我只得到文本元素。不接收长整数。

struct testStruct{
    char type;
    char field1[10];
    char field2[8];
    char field3[8];
    long num1, num2;
};


    testStruct ls;
    ls.type = 'U';

    strcpy(ls.field1, "NAVEENSHAR");
    strcpy(ls.field2, "abcd1234");
    strcpy(ls.field3, "al345678");
    ls.num1 = 40;
    ls.num2 = 200;
    char* bytes = static_cast<char*>(static_cast<void*>(&ls));
    bytes_sent = send(socketfd, bytes, sizeof(ls), 0);
    cout << "bytes sent: " << bytes_sent<< "\n";

    //On server sidechar
    incomming_data_buffer[1000];
    bytes_recieved = recv(new_sd, incomming_data_buffer,1000, 0);
    cout << "|" << incomming_data_buffer << "|\n";

它显示接收到的 48 个字节并且没有我添加的尾随整数。 关于为什么会发生这种情况的任何想法。我读过关于使用 boost 序列化发送结构的文章,但同时对于简单结构来说开销很大。

【问题讨论】:

  • sizeof(testStruct) 是 48 because of alignmentlongs 必须在 sizeof(long) 边界上对齐,这在您的机器上显然是 8 个字节。另一方面,chars 只需要对齐 1 个字节。前四个成员有 27 个字节,因此编译器必须在 field3long 之间添加额外的填充(5 个字节)才能使对齐工作。所以 27+5 字节 = 32 字节,为两个 longs 提供了正确的对齐方式(并解释了 5 字节的差异)。
  • 另请注意,您的字符串字段对于您要复制到它们的字符串来说太小了 - 显然您不允许使用 \0 终止符。以后再使用 strcpy 来避免出现这种错误时内存损坏。
  • @PaulR,是否需要 \0?我只使用strcpy?没明白你的意思。
  • C 字符串总是有一个终止符 \0,例如“abcd1234”实际上是9个字符,所有这些都将被strcpy复制,因此写在你的8个字符串field2的末尾。
  • @PaulR,谢谢,我改成了 memcpy。应该这样做。

标签: c++ sockets struct


【解决方案1】:

您几乎肯定会收到所有数据。问题出在这一行:

cout << "|" << incomming_data_buffer << "|\n";

incomming_data_buffer 打印为C 样式字符串,因此在第一个零字节处停止。由于您的 long 值是用二进制编码的,因此至少会有零(字段之间的填充也可能是零)。

您可以尝试执行以下操作:

cout << "|";
for (int i = 0; i < bytes_received; i++)
{
    cout << hex << (((int)incomming_data_buffer[i]) & 0xff) << " ";
}
cout << "|\n";

显示您收到的包裹的所有字节。

【讨论】:

  • 我试过了,但是遇到了一些奇怪的 cout 错误,invalid operands of type int and char[2] for operator &lt;&lt;
  • &amp; 0xff 的数学表达式周围需要另一组括号。现已编辑。
  • 我看到收到的所有字节,但我认为服务器希望 long 立即开始发布第三个 char 字段。有什么方法可以实现这一点并避免填充?
  • 您最好的选择可能是编写一些将数据序列化为字节缓冲区的代码。尽管有很多方法可以让许多编译器打包结构,但也有许多处理器架构在读取未对齐(未填充)的数据时会导致不正确的结果或崩溃。
猜你喜欢
  • 2020-09-17
  • 1970-01-01
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
相关资源
最近更新 更多