何时在C中使用ntohs和ntohl?

何时在C中使用ntohs和ntohl?,第1张

概述我很困惑何时使用ntohs和ntohl.我知道你在uint16_t和ntohl uint32_t使用ntohs的时候.但是那些使用unsigned int的那些或者指定了特定位数的那些(例如u_int16_t doff:4;). 这是我的工作代码来说明问题: // Utility/Debugging method for dumping raw packet datavoid dump(cons @H_404_4@ 我很困惑何时使用ntohs和ntohl.我知道你在uint16_t和ntohl uint32_t使用ntohs的时候.但是那些使用unsigned int的那些或者指定了特定位数的那些(例如u_int16_t doff:4;).

这是我的工作代码来说明问题:

// Utility/DeBUGging method for dumPing raw packet datavoID dump(const unsigned char *data,int length) {    unsigned int i;    static unsigned long pcount = 0;    // Decode Packet header    struct ether_header *eth_header = (struct ether_header *) data;    printf("\n\n === PACKET %ld header ===\n",pcount);    printf("\nSource MAC: ");    for (i = 0; i < 6; ++i) {        printf("%02x",eth_header->ether_shost[i]);        if (i < 5) {            printf(":");        }    }    printf("\nDestination MAC: ");    unsigned short ethernet_type = ntohs(eth_header->ether_type);    printf("\nType: %hu\n",ethernet_type); //Why not nthos?    if (ethernet_type == ETHERTYPE_IP) { //IP header        printf("\n == IP header ==\n");        struct ip *ip_hdr = (struct iP*) (data + sizeof(struct ether_header));        unsigned int size_ip = ip_hdr->ip_hl * 4; //why no nthos or nthol        printf("\nip_hdr->ip_hl: %u",ip_hdr->ip_hl); //why no nthos or nthol        printf("\nIP Version: %u",ip_hdr->ip_v); //why no nthos or nthol        printf("\nheader Length: %u",ip_hdr->ip_hl); //why no nthos or nthol        printf("\nTotal Length: %hu",ntohs(ip_hdr->ip_len)); //?is this right?        // TCP header        printf("\n== TCP header ==\n");        struct tcphdr *tcp_hdr = (struct tcphdr*) (data + sizeof(struct ether_header) + size_ip);        unsigned int size_tcp = tcp_hdr->doff * 4; //why no nthos or nthol        printf("\n Source Port: %" PRIu16,ntohs(tcp_hdr->th_sport));         printf("\n Destination Port: %" PRIu16,ntohs(tcp_hdr->th_dport));        printf("\n fin: %" PRIu16,tcp_hdr->fin ); //As this is 1 bit,both nthos or nthol will work        printf("\n urg: %" PRIu16,tcp_hdr->urg ); //As this is 1 bit,both nthos or nthol will work        printf("\n ack_seq: %" PRIu32,ntohl(tcp_hdr->ack_seq));        u_int16_t sourcePort = ntohs(tcp_hdr->th_sport);        u_int16_t destinationPort = ntohs(tcp_hdr->th_sport);        if (sourcePort == 80 || destinationPort == 80){            printf("\n\nPORT 80!!!\n");            //Transport payload!            printf("\n\  === TCP PAYLOAD DATA == \n");            // Decode Packet Data (SkipPing over the header)            unsigned int headers_size = ETH_HLEN + size_ip + size_tcp;            unsigned int data_bytes = length - headers_size;            const unsigned char *payload = data + headers_size;            const static int output_sz = 500; // Output this many bytes at a time            while (data_bytes > 0) {                int output_bytes = data_bytes < output_sz ? data_bytes : output_sz;                // Print data in raw hexadecimal form                printf("| ");                // Print data in ascii form                for (i = 0; i < output_bytes; ++i) {                    char byte = payload[i];                    if ( (byte > 31 && byte < 127) || byte == '\n') {                        // Byte is in printable ascii range                        printf("%c",byte);  //why no nthos or nthol                    } else {                        printf(".");                    }                }                payload += output_bytes;                data_bytes -= output_bytes;            }        }    }    pcount++;}

正如你所看到的,我有时会使用ntohs / ntohl,有时我也不使用ntohs / ntohl.我不明白何时使用哪个.

@H_404_4@解决方法

But what about those with unsigned int

原则上,如上所述,C不保证unsigned int的大小;有一些平台,其中int和unsigned int是16位,例如PDP-11,摩托罗拉68k处理器和一些编译器(其他编译器使它们成为32位),对于某些16-可能仍然如此位微处理器.

因此,如果您通过网络发送数据,最好使用< stdint.h>中定义的类型.如果可以的话.

实际上,你使用的机器几乎肯定会有一个32位无符号整数,although some Cray machines have 64-bit int and even short!但是最好还是使用< stdint.h>中定义的类型.

or those where a specific amount of bits is specifIEd (e.g. u_int16_t doff:4;).

如果一个值短于一个字节,就像4位字段的情况那样,字节顺序是无关紧要的.

但是,请注意,C,也不指定1,2或4字节序列中的位字段顺序,因此不应在通过线路发送的数据中使用位字段. (是的,一些UN * Xes碰巧在IPv4和TCP头的结构中使用它们,但这只有在供应商用于支持所有以相同顺序放置位域的架构的编译器时才有效,如果是第三方像GCC这样的编译器做同样的事情.)

因此,处理IPv4标头的正确方法是执行诸如此类 *** 作

struct ip {        uint8_t         ip_vhl;         /* header length,version */#define IP_V(ip)        (((ip)->ip_vhl & 0xf0) >> 4)#define IP_HL(ip)       ((ip)->ip_vhl & 0x0f)        uint8_t         ip_tos;         /* type of service */        uint16_t        ip_len;         /* total length */        uint16_t        ip_ID;          /* IDentification */        uint16_t        ip_off;         /* fragment offset fIEld */#define IP_DF 0x4000                    /* dont fragment flag */#define IP_MF 0x2000                    /* more fragments flag */#define IP_OFFMASK 0x1fff               /* mask for fragmenting bits */        uint8_t         ip_ttl;         /* time to live */        uint8_t         ip_p;           /* protocol */        uint16_t        ip_sum;         /* checksum */        struct  in_addr ip_src,ip_dst;  /* source and dest address */};

使用该结构声明ip_hdr指向IP头的指针,并且:

>提取版本,使用IP_V(ip_hdr);
>提取标头长度,使用IP_HL(ip_hdr).

如果供应商的ip.h标头使用位域,请不要使用供应商的ip.h标头;使用自己的标题.实际上,即使您的供应商的ip.h标头不使用位域,也不要使用供应商的ip.h标头;使用自己的标题.毕竟,并不是因为IP头的定义依赖于 *** 作系统….

(这就是tcpdump现在为几个版本所做的事情;上面是从它的ip.h中获取的.)

@H_404_4@ @H_404_4@ @H_404_4@ @H_404_4@ 总结

以上是内存溢出为你收集整理的何时在C中使用ntohs和ntohl?全部内容,希望文章能够帮你解决何时在C中使用ntohs和ntohl?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1216392.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存