2015-02-04 2 views
1

В функциях как connect() последним параметром является размер структуры sockaddr_in.Какое значение имеет параметр sizeof (sockaddr_in)

Все хорошо, но sin_zero не используется (система не «pop sin_zero», как я понял в stackoverflow.com/questions/28280581/how-kernels-recognize-sin-zero-sockaddr-in-structure-pushed), поэтому для чего нужны функции этого параметра?

I.e. asm или когда C скомпилирован в asm, RET соединения() должен указать количество удаляемых байтов (RET n), байты, которые являются аргументами connect(). Почему n - это фиксированное число (не меняйте значение sin_zero или нет), если я могу нажать или нет sin_zero в asm и присвоить значение sin_zero в C. И если я создам программу в asm, и я не буду нажимать sin_zero в стек, программы отлично работают ... но n - это то же самое число!

+0

Я не уверен, что вы подразумеваете под словом "pop sin_zero"? То, что вы должны передать 'connect', это' sockaddr * '. Нет ничего, что говорило бы о том, что структура 'sockaddr' должна быть распределена по стекам, а также функция' connect'. – Michael

+0

Подсказка: эти функции принимают 'struct sockaddr *', но вы обычно передаете другую вещь, 'struct sockaddr_in *'. Ты знаешь почему? –

+0

Michael: Я говорю «pop sin_zero», ссылаясь на то, что функция заканчивает «sin_zero» вычитается из стека. – Rob

ответ

1

A sockaddr_in - это структура, содержащая адрес в Интернете. Эта структура определена в <netinet/in.h>. Это адрес сервера/клиента struct sockaddr_in serv_addr, cli_addr; Вот определение:

struct sockaddr_in { 
    short sin_family; 
    u_short sin_port; 
    struct in_addr sin_addr; 
    char sin_zero[8]; 
}; 

sin_family - использование AF_INET sin_port - номер порта (в сетевом порядке байт => использовать htons(port)) sin_addr - Интернет-адрес, описанный структуры in_addr

struct in_addr { 
     unsigned long s_addr; 
}; 

s_addr - INADDR_ANY => местный адрес в Интернете. sin_zero[] - установлен на 0 с bzero() или memset(). Заполнение, чтобы сделать структуру того же размера, что и SOCKADDR.

привязывать) пример (

int mysock,err; 
struct sockaddr_in myaddr; 
mysock = socket(AF_INET,SOCK_STREAM,0); 
myaddr.sin_family = AF_INET; 
myaddr.sin_port = htons(portnum); 
myaddr.sin_addr.s_addr = INADDR_ANY; 
bzero(&(myaddr.sin_zero),sizeof(myaddr.sin_zero)); 
err = bind(mysock, (struct sockaddr *) &myaddr, sizeof(myaddr)); 

Я нашел некоторую информацию о sin_zero (Unix сетевого программирования глава 3,2)

Спецификация POSIX требует только три членов в структуре: sin_family, sin_addr, и sin_port. Для реализации, совместимой с POSIX, допустимо определить дополнительные члены структуры, и это нормально для структуры адресов сокета в Интернете. Почти все реализации добавляют член sin_zero, так что все структуры адресов сокетов имеют размер не менее 16 байт.

И определение sin_zero

unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) 
        - sizeof(unsigned short int) - sizeof(struct in_addr)]; 
}; 
#define sin_zero  __pad 

Большая часть чистого кода не использует sockaddr_in, он использует SOCKADDR. Когда вы используете функцию sendto, вы должны явно указать sockaddr_in или любой другой адрес, используемый вами, в sockaddr. sockaddr_in - тот же размер, что и sockaddr, но внутренне размеры одинаковы из-за небольшого взлома.

Этот хак является sin_zero. На самом деле длина полезных данных в sockaddr_in короче, чем sockaddr. Но разница добавляется в sockaddr_in с использованием небольшого буфера; этот буфер является sin_zero.

На некоторых архитектурах это не вызовет никаких проблем, не устраняющих sin_zero. Но на других архитектурах это может быть.Для этого требуется спецификация, чтобы очистить sin_zero, поэтому вы должны это сделать, если вы намереваетесь, чтобы ваш код был недоступен в настоящее время и в будущем.

Пожалуйста, взгляните на page.

+0

Хороший ответ. Я отредактировал сообщение, указав больше, потому что я не знаю, как процесс sin_zero. – Rob

+0

Процесс с помощью клиринга? –

+0

Что? Я говорю о том, как система обрабатывает значение sin_zero, значение присвоено или нет. – Rob

0

Я думаю, что ядро ​​использует параметр размера, чтобы видеть, что ваш sockaddr является адресом ipv6 или нет, потому что размер адреса ipv6 больше, чем другой сетевой адрес в linux и unix.

0

Возможно, это проблема архитектуры, на разных архитектурах, таких как 64-битный/32-разрядный размер примитива, объявленного в sockaddr_in, будет отличаться. Вот почему это может быть параметр, объявленный в функции connect().

Смежные вопросы