在 C/C++ 中创建和发送原始数据包

Creating and sending raw data packets in C/C++

我知道我的包裹是什么样子的。它有 6 header 个字段(每个 1 个字节,每个 header 有 8 个字段)然后它有有效负载(数据)。

我想用 C 或 C++ 构建一个原始数据包(我认为它应该看起来一样)。

这是我认为我应该做的:

    unsigned char packet[11];

    packet[0] = (0x81); // first header with 8 fields
    packet[1] = (0x8c); // second header with 8 fields
    packet[2] = (0xfe);
    packet[3] = (0x84);
    packet[4] = (0x1d);
    packet[5] = (0x79);
    packet[6] = (0x96); // payload, the 'h' letter, masked
    packet[7] = (0xe1); // 'e'
    packet[8] = (0x71); // 'l'
    packet[9] = (0x15); // 'l'
    packet[10] = (0x91);// 'o'

例如,0x81 是第一个字节(我只是将第一个 header 的每个字段(位)转换为十六进制)。

然后,简单地说,我想将它发送到服务器:send(sockfd, packet, sizeof(packet), 0) 来发送它。

接收并打印响应:

unsigned char buffer[1024];
if ((recv(sockfd, buffer, len, 0)) == 0)
    {
        if (errno != 0)
        {
            exit(1);
        }
    }

    int i;
    for(i = 0; i<len; i++)
        printf("%x ", buffer[i]);

我说的对吗?

您的代码不会出现错误!

但一个好的做法是:

const std::uint32_t BUFFER_SIZE = 11;

std::vector<std::uint8_t> buffer;
buffer.reserve(BUFFER_SIZE)

buffer = {0x81,0x8c.....};

send( sockfd,
      reinterpret_cast <const char*> ( buffer.data() ),
      static_cast      <int>         ( buffer.size() ),
      0
      );

这样做,您的代码会得到更优化,并避免可能的泄漏,使用 std 向量。

查看 ZeroMQ 也可能会受益,将其作为现成的高性能异步消息传递库的示例,旨在用于分布式或并发应用程序。

除了错误处理 recv 中的 return 值外,您的代码看起来还不错。

if ((recv(sockfd, buffer, len, 0)) == 0)
    {
        if (errno != 0)
        {
            exit(1);
        }
    }

零return表示连接正常关闭。如果 return 为零,则没有理由检查 errno

-1 的 return 值表示错误。在这种情况下,检查 errno.

确实有意义

大于零的值表示已收到字节数。请注意,recv 到 return 个字节比您要求的少是完全正常的。如果您想准确接收一定数量的字节,则必须在循环中调用 recv

TCP 是一种字节流协议,不知道您的 "packets"(实际上是消息)的开始和结束位置。