简体   繁体   English

通过C套接字发送结构

[英]Sending structs over a C socket

I'm writing a DNS query client and can't understand how my data is being sent and how to make it work correctly. 我正在编写DNS查询客户端,但无法理解我的数据如何发送以及如何使其正常工作。

In Wireshark, I'm getting a lot of random data with MALFORMED PACKET warnings, and no response from the DNS server I'm testing with. 在Wireshark中,我收到了许多带有MALFORMED PACKET警告的随机数据,而正在测试的DNS服务器没有响应。 (currently Google's DNS... 8.8.8.8) (当前是Google的DNS ... 8.8.8.8)

A snippet... 一段...

typedef struct DNS_HEADER {

    // id to identify the request
    int16_t id;

    // query or response flag; default is 0
    uint8_t qr :1;

    // type of query; default is 0
    uint8_t opcode :4;

    // authoritative answer
    uint8_t aa :1;

    // message was truncated
    uint8_t tc :1;

    // recursion desired; default is yes
    uint8_t rd :1;

    // recursion available
    uint8_t ra :1;

    // unused
    uint8_t z :1;

    // response code
    uint8_t rcode :4;

    // entries in the question section; default is 1
    uint16_t qdcount;

    // resource records
    uint16_t ancount;

    // server resource records (in the authority section)
    uint16_t nscount;

    // resource records (in addl. section)
    uint16_t arcount;

} dns_h;

header->qr = 0;
header->opcode = 0;
...
header->qdcount = htons(1);
...

And my sendto... 还有我的信箱

char buffer[sizeof(*header) * sizeof(*question) * 2];
int offset = 0;
memcpy(buffer, header, sizeof(*header));
offset += sizeof(*header);
memcpy(buffer + offset, question, sizeof(*question)); 

ssize_t sent = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)addr, sizeof(*addr));

What am I doing wrong? 我究竟做错了什么? Is this the recommended way to send a struct over a socket? 这是通过套接字发送结构的推荐方法吗? I've set most fields in the header to 0 and anything I've set to 1 I've used htons 我已将标题中的大多数字段设置为0,并将任何我设置为1的内容都使用了htons

Two problems with your header struct: 标头结构有两个问题:

  • The z field is 3 bits, not 1. So the rcode field is two bits left of where it should be. z字段是3位,而不是1。因此, rcode字段在应保留的位置还剩两位。
  • The fact that you're using bitfields at all. 您完全使用位域的事实。 To get this right you'd need to know the endianness at compile time and there's no portable way to do this. 为了实现这一目标,您需要在编译时知道字节序,并且没有可移植的方法来执行此操作。 You're better off declaring a single 16-bit field (or 2 8-bit fields) for everything and bit shifting to read/write the proper values. 您最好为所有内容声明一个16位字段(或2个8位字段),并进行位移以读取/写入适当的值。

You don't show the code where you're creating the header, but make sure you use htons when setting the fields so that the values are in network byte order. 您没有在头文件的创建位置显示代码,而是在设置字段时确保使用htons ,以使值以网络字节顺序排列。

Also, take a close look at the binary data in the packet in Wireshark. 另外,请仔细查看Wireshark中数据包中的二进制数据。 Compare that with the values you put in to see what's out of place. 将其与您输入的值进行比较,看看有什么地方不对。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM