Подумайте о записи , как это реализовано , как: #define write(...) send(##__VA_ARGS__, 0).
внимательнее1
Ответы:
128
Разница в том, что recv()/ send()работают только с дескрипторами сокетов и позволяют указывать определенные параметры для реальной операции. Эти функции немного более специализированы (например, вы можете установить флаг, чтобы игнорировать SIGPIPEили отправлять внеполосные сообщения ...).
Функции read()/ write()- это универсальные функции файловых дескрипторов, работающие со всеми дескрипторами.
Это неверно, есть еще одно отличие в случае дейтаграмм 0 длины - если датаграмма нулевой длины находится в ожидании, read (2) и recv () с аргументом flags, равным нулю, обеспечивают другое поведение. В этом случае read (2) не имеет никакого эффекта (дейтаграмма остается ожидающей), тогда как recv () использует ожидающую дейтаграмму.
Абхинав Гауниал
2
@AbhinavGauniyal Как это обеспечит другое поведение ? Если есть 0-байтовая дейтаграмма, и то, recvи другое readне доставит данные вызывающей стороне, но также не даст ошибки. Для звонящего поведение такое же. Вызывающий может даже не знать ничего о дейтаграммах (он может не знать, что это сокет, а не файл, он может не знать, что это сокет дейтаграммы, а не сокет потока). То, что датаграмма остается в ожидании, является неявным знанием того, как стеки IP работают в ядрах и невидимы для вызывающей стороны. С точки зрения вызывающих, они все равно будут обеспечивать равное поведение.
Меки
2
@Mecki, это не скрытое знание для всех, возьмите меня к примеру :)
Абхинав Гауниял
1
@Mecki, что означает неблокирующее успешное чтение 0 байтов? Датаграмма все еще остается в ожидании? Именно это и только это беспокоит меня: поведение, которое дейтаграмма может ожидать, даже если успешно прочитано. Я не уверен, что ситуация может возникнуть, поэтому я хотел бы иметь это в виду.
Се
2
@sehe Если вы беспокоитесь, почему бы вам не использовать recv? Причиной, по которой recvи sendгде в первую очередь была введена информация, был тот факт, что не все концепции дейтаграмм можно сопоставить с миром потоков. readи writeобрабатывать все как поток данных, будь то канал, файл, устройство (например, последовательный порт) или сокет. Тем не менее, сокет является только реальным потоком, если он использует TCP. Если он использует UDP, он больше похож на блочное устройство. Но если обе стороны используют его как поток, он будет работать как поток, и вы даже не сможете отправить пустой пакет UDP с помощью writeвызовов, поэтому такая ситуация не возникнет.
Я только недавно заметил, что когда я использовал write()сокет в Windows, он почти работает (передаваемый FD write()не совпадает с передаваемым send(); я использовал _open_osfhandle()для передачи FD write()). Тем не менее, это не сработало, когда я попытался отправить двоичные данные, которые включали символ 10. write()где-то вставил символ 13 до этого. Изменение этого send()параметра с параметром flags, равным 0, решило эту проблему. read()может иметь обратную проблему, если 13-10 последовательных в двоичных данных, но я не проверял это. Но это, кажется, другая возможная разница между send()и write().
«Производительность и скорость»? Разве это не ... синонимы здесь?
В любом случае, recv()вызов принимает флаги, которые read()этого не делают, что делает его более мощным или, по крайней мере, более удобным. Это одно из отличий. Я не думаю, что есть существенная разница в производительности, но я не проверял это.
Возможно, отсутствие необходимости иметь дело с флагами может быть воспринято как более удобное.
Семай
2
В Linux я также заметил, что:
Прерывание системных вызовов и функций библиотеки обработчиками сигнала
Если обработчик сигнала вызывается, когда системный вызов или вызов функции библиотеки заблокированы, то либо:
вызов автоматически перезапускается после возврата обработчика сигнала; или
вызов не выполняется с ошибкой EINTR.
... Детали различаются в разных системах UNIX; ниже, подробности для Linux.
Если заблокированный вызов одного из следующих интерфейсов прерывается обработчиком сигнала, то вызов автоматически перезапускается после того, как обработчик сигнала возвращается, если использовался флаг SA_RESTART; в противном случае вызов завершается с ошибкой EINTR:
вызовы read (2), readv (2), write (2), writev (2) и ioctl (2) на «медленных» устройствах.
.....
Следующие интерфейсы никогда не перезапускаются после прерывания обработчиком сигнала, независимо от использования SA_RESTART; они всегда терпят неудачу с ошибкой EINTR при прерывании обработчиком сигнала:
«Входные» сокетные интерфейсы, когда тайм-аут (SO_RCVTIMEO) был установлен на сокете с помощью setsockopt (2): accept (2), recv (2),
recvfrom (2), recvmmsg (2) (также с ненулевым значением) аргумент тайм-аута) и recvmsg (2).
«Выходные» интерфейсы сокетов, когда для сокета было установлено время ожидания (SO_RCVTIMEO) с использованием setsockopt (2): connect (2), send (2), sendto (2) и sendmsg (2).
Проверьте man 7 signalдля более подробной информации.
Простое использование будет использовать сигнал, чтобы избежать recvfromблокировки на неопределенный срок.
#define write(...) send(##__VA_ARGS__, 0)
.Ответы:
Разница в том, что
recv()
/send()
работают только с дескрипторами сокетов и позволяют указывать определенные параметры для реальной операции. Эти функции немного более специализированы (например, вы можете установить флаг, чтобы игнорироватьSIGPIPE
или отправлять внеполосные сообщения ...).Функции
read()
/write()
- это универсальные функции файловых дескрипторов, работающие со всеми дескрипторами.источник
recv
и другоеread
не доставит данные вызывающей стороне, но также не даст ошибки. Для звонящего поведение такое же. Вызывающий может даже не знать ничего о дейтаграммах (он может не знать, что это сокет, а не файл, он может не знать, что это сокет дейтаграммы, а не сокет потока). То, что датаграмма остается в ожидании, является неявным знанием того, как стеки IP работают в ядрах и невидимы для вызывающей стороны. С точки зрения вызывающих, они все равно будут обеспечивать равное поведение.recv
? Причиной, по которойrecv
иsend
где в первую очередь была введена информация, был тот факт, что не все концепции дейтаграмм можно сопоставить с миром потоков.read
иwrite
обрабатывать все как поток данных, будь то канал, файл, устройство (например, последовательный порт) или сокет. Тем не менее, сокет является только реальным потоком, если он использует TCP. Если он использует UDP, он больше похож на блочное устройство. Но если обе стороны используют его как поток, он будет работать как поток, и вы даже не сможете отправить пустой пакет UDP с помощьюwrite
вызовов, поэтому такая ситуация не возникнет.За первое попадание в Google
источник
recv
может быть использован только на сокете, и выдаст ошибку , если вы пытаетесь использовать его, скажем,STDIN_FILENO
.read()
иwrite()
являются более общими, они работают с любым файловым дескриптором. Тем не менее, они не будут работать на Windows.Вы можете передать дополнительные опции
send()
иrecv()
, поэтому вам, возможно, придется использовать их в некоторых случаях.источник
Я только недавно заметил, что когда я использовал
write()
сокет в Windows, он почти работает (передаваемый FDwrite()
не совпадает с передаваемымsend()
; я использовал_open_osfhandle()
для передачи FDwrite()
). Тем не менее, это не сработало, когда я попытался отправить двоичные данные, которые включали символ 10.write()
где-то вставил символ 13 до этого. Изменение этогоsend()
параметра с параметром flags, равным 0, решило эту проблему.read()
может иметь обратную проблему, если 13-10 последовательных в двоичных данных, но я не проверял это. Но это, кажется, другая возможная разница междуsend()
иwrite()
.источник
Еще одна вещь на Linux:
send
не позволяет работать на не-сокете fd. Таким образом, например, чтобы написать на USB-порт,write
необходимо.источник
«Производительность и скорость»? Разве это не ... синонимы здесь?
В любом случае,
recv()
вызов принимает флаги, которыеread()
этого не делают, что делает его более мощным или, по крайней мере, более удобным. Это одно из отличий. Я не думаю, что есть существенная разница в производительности, но я не проверял это.источник
В Linux я также заметил, что:
Проверьте
man 7 signal
для более подробной информации.Простое использование будет использовать сигнал, чтобы избежать
recvfrom
блокировки на неопределенный срок.Пример из APUE :
источник