Я изучаю сетевое программирование с помощью 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
только taks в 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 бит, нет беспокойства по поводу endianess. Вот и все. Вы не можете изменить порядок байтов в одном байте.
Это довольно просто. Вам понадобятся ntohs
(чтение Net TO Host для коротких значений) всякий раз, когда вы получаете 16-битное значение в полученной по сети. Причиной является эндиантность различных систем при кодировании этих чисел в многобайтовые.
ntohs
- это сеть для хоста - короткая. Короткий - 16 бит. Примером использования ntohs является 16-разрядное значение "порт", если вы извлекаете значение порта из структуры sockaddr.
uint16_t portNo = ntohs(sock.sin_port);
вы должны делать конверсию, htons, когда oyu помещает номер порта в структуры sockaddr в первую очередь.
Вам нужно использовать его только в тех местах, где вы ожидаете преобразования endianess. Части заголовков и протокольные переменные, в частности. Для пользовательской части пакетов (ваши данные) это по вашему усмотрению.