Формальная разница в параметрах sendto () и recvfrom () в C

Я использую recvfrom() и _ 2_ для приема и отправки пакетов UDP.

Я заметил, что recvfrom() в качестве последнего параметра требует указателя на переменную, хранящего длину адреса сервера, в то время как sendto() требует переменной, в которой хранится длина адреса клиента.

Почему такая разница?


person Tommaso Bendinelli    schedule 18.10.2019    source источник
comment
Вы пробовали читать описания функций?   -  person Vlad from Moscow    schedule 18.10.2019
comment
Receive хочет где-нибудь указать размер, который он прочитал; send необходимо знать только длину, и мы не будем ее изменять.   -  person Paul Ogilvie    schedule 18.10.2019


Ответы (2)


Поскольку UDP не основан на соединении (нет connect(sd, ...) вызова, в котором вы говорите: с этого момента все данные, относящиеся к дескриптору сокета sd, будут поступать от хорошо известной пары IP-портов), всякий раз, когда вы запускаете recvfrom(), он (пытается) вернуть вы - адрес, откуда поступают входящие данные.

Он записывает адрес в буфер src_addr, если он не равен NULL. Этот буфер предоставляется вызывающей стороной, и его размер должен быть указан в параметре addr_len. Он передается по указателю, потому что recvfrom(), после использования его для ограничения количества данных, записываемых в src_addr, перезапишет его с помощью фактической длины адреса. Можно сказать, что addr_len - это параметр ввода-вывода.

С другой стороны, вызывающий sendto() будет точно знать адрес назначения, поэтому addr_len в этом случае передается по значению, поскольку является параметром только для ввода.

Эта информация четко объяснена в руководстве, на которое вы указали ссылку в вопросе.

person Roberto Caboni    schedule 18.10.2019
comment
Спасибо! Я запутался в жаргонных словах, и поэтому руководство оказалось бесполезным. Причина в том, что фактическая длина адреса известна из-за того, что сеть UDP не основана на подключении. Таким образом, мы передаем по указателю, потому что это значение можно изменить. - person Tommaso Bendinelli; 18.10.2019
comment
На самом деле существует возможность вызвать connect () на UDP, чтобы указать (единственный) удаленный адрес (но не на самом деле общаться, как TCP с обменом SYN / ACK) и впоследствии используйте send () и recv () с неявным адресом; см. linux.die.net/man/7/udp et rel. Но sendto () recvfrom () sendmsg () recvmsg () без connect () чаще используются и работают так, как вы описываете. - person dave_thompson_085; 18.10.2019

Я заметил, что recvfrom () в качестве последнего параметра требует указателя на переменную, хранящую длину адреса сервера, в то время как sendto () требует переменной, хранящей длину адреса клиента.

Вы на самом деле отвечаете на свой вопрос

recvfrom() as last parameter requires a pointer to
the variable storing the length of server address.


while sendto() requires the variable that stores 
the length of the client address.

recvfrom() нужен указатель, потому что он сохраняет значение в том месте, куда указывает этот указатель. Поскольку в c нет ничего, что называется вызовом по ссылке, вам необходимо передать указатель, чтобы имитировать поведение вызова по ссылке.

person kiran Biradar    schedule 18.10.2019
comment
Это в основном правильно, но обратите внимание, что вызов по ссылке - это довольно общая / абстрактная концепция, которую можно увидеть как реализованную, передав указатели в качестве аргументов функции в C. скажем, c поддерживает вызов по ссылке - person Ctx; 18.10.2019
comment
@Ctx нет, это неправильно. C поддерживает только вызов по значению. Вы можете эмулировать указатели передачи вызова по ссылке, но это не означает, что C поддерживает его (он не является родным для языка). - person Jean-Baptiste Yunès; 18.10.2019
comment
Спасибо, Киран Бирадар, за ваш ответ, и спасибо Жан-Батизу Юнесу. Почему recvfrom нужно место, куда указывает указатель, а sendto - нет? - person Tommaso Bendinelli; 18.10.2019
comment
@ Jean-BaptisteYunès Это очень узкий взгляд на те концепции, типичные для программистов. - person Ctx; 18.10.2019