Я изучаю сетевое программирование с использованием WinPcap. Вот фрагмент:
int ip_hlen = (ih->ver_ihl & 0xf) * 4; /* get ip header length */
tcp_header *th = (tcp_header *) ((u_char*)ih + ip_len);
int tcp_hlen = (ntohs(th->th_len_resv_code) & 0xf000) >> 12)*4; /* get tcp header length */
Проблема в том, почему ntohs
используется только при получении tcp_hlen
не ip_hlen
,
В самом деле, ntohs
только берет в u_short
как параметр объясняет немного. http://msdn.microsoft.com/en-us/library/windows/desktop/ms740075%28v=vs.85%29.aspx
Я все еще озадачен при использовании ntohs, когда нет.
Вот структура определения пакетов IP и TCP:
/* ipv4 header */
typedef struct ip_header {
u_char ver_ihl; /* version and ip header length */
u_char tos; /* type of service */
u_short tlen; /* total length */
u_short identification; /* identification */
u_short flags_fo; // flags and fragment offset
u_char ttl; /* time to live */
u_char proto; /* protocol */
u_short crc; /* header checksum */
ip_address saddr; /* source address */
ip_address daddr; /* destination address */
u_int op_pad; /* option and padding */
}ip_header;
/* tcp header */
typedef struct tcp_header {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
u_int th_seq; /* sequence number */
u_int th_ack; /* acknowledgement number */
u_short th_len_resv_code; /* datagram length and reserved code */
u_short th_window; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
}tcp_header;
Поскольку Поле длины IP-заголовка он настолько мал (всего четыре бита), что предполагается помещаться в один байт, и поэтому у него никогда не может быть проблем с порядком байтов. Существует только один байт, поэтому нет байтов для замены с помощью ntohs()
функция.
Если ваше значение равно 8 битам, вам не нужно беспокоиться о порядке байтов. Это все. Вы не можете переупорядочить байты в одном байте.
ntohs
Сеть к хосту — короткая. Короткое замыкание — 16 бит. Примером использования ntohs является 16-битное значение ‘port’, если вы извлекаете значение порта из структуры sockaddr.
uint16_t portNo = ntohs(sock.sin_port);
вы должны делать конверсию, htons, когда в первую очередь вы вводите номер порта в структуры sockaddr.
Вам нужно использовать его только в тех местах, где вы ожидаете преобразования endianess. Части заголовков и переменные протокола, в частности. Для пользовательской части пакетов (ваших данных) это на ваше усмотрение.
Это довольно просто. Тебе понадобиться ntohs
(читать Net TO Host конвертация для коротких значения) всякий раз, когда вы сталкиваетесь с 16-битным значением, полученным по сети. Причина заключается в бесконечности различных систем при кодировании этих чисел в многобайтовые.