何时在C中使用ntohs和ntohl?
我很困惑何时使用ntohs和ntohl.我知道你在uint16_t和ntohl uint32_t使用ntohs的时候.但是那些使用unsigned int的那些或者指定了特定位数的那些(例如u_int16_t doff:4;).
这是我的工作代码来说明问题: // Utility/Debugging method for dumping raw packet data void 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("nn === 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: %hun",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("nnPORT 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.我不明白何时使用哪个. 解决方法
原则上,如上所述,C不保证unsigned int的大小;有一些平台,其中int和unsigned int是16位,例如PDP-11,摩托罗拉68k处理器和一些编译器(其他编译器使它们成为32位),对于某些16-可能仍然如此位微处理器. 因此,如果您通过网络发送数据,最好使用< stdint.h>中定义的类型.如果可以的话. 实际上,你使用的机器几乎肯定会有一个32位无符号整数,although some Cray machines have 64-bit
如果一个值短于一个字节,就像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.h标头使用位域,请不要使用供应商的ip.h标头;使用自己的标题.实际上,即使您的供应商的ip.h标头不使用位域,也不要使用供应商的ip.h标头;使用自己的标题.毕竟,并不是因为IP头的定义依赖于操作系统…. (这就是tcpdump现在为几个版本所做的事情;上面是从它的ip.h中获取的.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |