Pikirkan menulis seperti yang diterapkan seperti ini: #define write(...) send(##__VA_ARGS__, 0).
hati1 1
Jawaban:
128
Perbedaannya adalah bahwa recv()/ send()hanya bekerja pada deskriptor soket dan membiarkan Anda menentukan opsi tertentu untuk operasi yang sebenarnya. Fungsi-fungsi itu sedikit lebih khusus (misalnya, Anda dapat mengatur bendera untuk diabaikan SIGPIPE, atau untuk mengirim pesan out-of-band ...).
Fungsi read()/ write()adalah fungsi deskriptor file universal yang bekerja pada semua deskriptor.
Ini tidak benar, ada satu perbedaan lain dalam hal datagram dengan panjang 0 - Jika datagram panjang-nol tertunda, baca (2) dan recv () dengan argumen bendera nol memberikan perilaku yang berbeda. Dalam keadaan ini, baca (2) tidak memiliki efek (datagram tetap tertunda), sementara recv () mengkonsumsi datagram tertunda.
Abhinav Gauniyal
2
@AbhinavGauniyal Bagaimana hal itu memberikan perilaku yang berbeda ? Jika ada datagram 0 byte, keduanya, recvdan tidak readakan mengirimkan data ke pemanggil tetapi juga tidak ada kesalahan. Bagi penelepon, perilakunya sama. Penelepon mungkin bahkan tidak tahu apa-apa tentang datagram (mungkin tidak tahu bahwa ini adalah soket dan bukan file, mungkin tidak tahu bahwa ini adalah soket datagram dan bukan soket aliran). Bahwa datagram tetap tertunda adalah pengetahuan implisit tentang bagaimana tumpukan IP bekerja di kernel dan tidak terlihat oleh pemanggil. Dari perspektif penelepon, mereka masih akan memberikan perilaku yang sama.
Mecki
2
@Mecki itu bukan pengetahuan implisit untuk semua orang, ambil saya misalnya :)
Abhinav Gauniyal
1
@Mecki apa yang ditunjukkan oleh pembacaan sukses tanpa byte 0 byte? Apakah datagram masih tertunda? Tepatnya, dan hanya itu, yang mengkhawatirkan saya: perilaku yang datagram bisa tetap tertunda meskipun berhasil dibaca. Saya tidak yakin apakah situasinya dapat muncul, yang mana saya ingin mengingatnya.
sehe
2
@ Sehe Jika Anda khawatir, mengapa Anda tidak menggunakannya recv? Alasan mengapa recvdan di sendmana diperkenalkan di tempat pertama adalah fakta bahwa tidak semua konsep datagram dapat dipetakan ke dunia aliran. readdan writememperlakukan segala sesuatu sebagai aliran data, apakah itu pipa, file, perangkat (misalnya port serial) atau soket. Namun soket hanya aliran nyata jika menggunakan TCP. Jika menggunakan UDP itu lebih seperti perangkat blok. Tetapi jika kedua belah pihak menggunakannya seperti aliran, itu akan berfungsi seperti aliran dan Anda bahkan tidak dapat mengirim paket UDP kosong menggunakan writepanggilan, sehingga situasi ini tidak akan muncul.
read () sama dengan recv () dengan parameter flags 0. Nilai lain untuk parameter flags mengubah perilaku recv (). Demikian pula, write () sama dengan mengirim () dengan flag == 0.
Ini bukan keseluruhan cerita. recvhanya dapat digunakan pada soket, dan akan menghasilkan kesalahan jika Anda mencoba menggunakannya, katakan STDIN_FILENO,.
Joey Adams
76
Utas ini sekarang menjadi hit pertama di Google, Google menyukai stackoverflow
Eloff
12
read()dan write()lebih umum, mereka bekerja dengan deskriptor file apa pun. Namun, mereka tidak akan berfungsi di Windows.
Anda dapat memberikan opsi tambahan ke send()dan recv(), jadi Anda mungkin harus menggunakannya dalam beberapa kasus.
Saya baru-baru ini memperhatikan bahwa ketika saya menggunakan write()soket pada Windows, ia hampir berfungsi (FD yang diteruskan write()tidak sama dengan yang dilewati send(); saya biasa _open_osfhandle()menerima FD yang dilewati write()). Namun, itu tidak berfungsi ketika saya mencoba mengirim data biner yang menyertakan karakter 10. write()suatu tempat memasukkan karakter 13 sebelum ini. Mengubahnya menjadi send()dengan parameter flags 0 memperbaiki masalah itu. read()bisa memiliki masalah sebaliknya jika 13-10 berturut-turut dalam data biner, tapi saya belum mengujinya. Tapi itu tampaknya menjadi perbedaan lain yang mungkin antara send()dan write().
"Performa dan kecepatan"? Bukankah itu semacam ... sinonim, di sini?
Pokoknya, recv()panggilan itu mengambil bendera yang read()tidak, yang membuatnya lebih kuat, atau setidaknya lebih nyaman. Itu satu perbedaan. Saya tidak berpikir ada perbedaan kinerja yang signifikan, tetapi belum diuji untuk itu.
Mungkin tidak harus berurusan dengan bendera mungkin dianggap lebih nyaman.
semaj
2
Di Linux saya juga memperhatikan bahwa:
Gangguan panggilan sistem dan fungsi perpustakaan oleh penangan sinyal
Jika penangan sinyal dipanggil saat panggilan sistem atau panggilan fungsi perpustakaan diblokir, maka:
panggilan secara otomatis dimulai kembali setelah penangan sinyal kembali; atau
panggilan gagal dengan EINTR kesalahan.
... Detail bervariasi di seluruh sistem UNIX; di bawah ini, detail untuk Linux.
Jika panggilan yang diblokir ke salah satu antarmuka berikut diinterupsi oleh penangan sinyal, maka panggilan secara otomatis dimulai kembali setelah penangan sinyal kembali jika bendera SA_RESTART digunakan; jika tidak panggilan gagal dengan EINTR kesalahan:
read (2), readv (2), write (2), writev (2), dan ioctl (2) memanggil perangkat "lambat".
.....
Antarmuka berikut tidak pernah dihidupkan ulang setelah terganggu oleh penangan sinyal, terlepas dari penggunaan SA_RESTART; mereka selalu gagal dengan EINTR kesalahan ketika diinterupsi oleh penangan sinyal:
Antarmuka soket "Input", ketika batas waktu (SO_RCVTIMEO) telah diset pada soket menggunakan setockopt (2): accept (2), recv (2),
recvfrom (2), recvmmsg (2) (juga dengan non-NULL argumen timeout), dan recvmsg (2).
Antarmuka soket "Output", ketika batas waktu (SO_RCVTIMEO) telah ditetapkan pada soket menggunakan setockopt (2): sambungkan (2), kirim (2), kirimto (2), dan sendmsg (2).
Memeriksa man 7 signal lebih detail.
Penggunaan sederhana akan menggunakan sinyal untuk menghindari recvfrompemblokiran tanpa batas.
#define write(...) send(##__VA_ARGS__, 0)
.Jawaban:
Perbedaannya adalah bahwa
recv()
/send()
hanya bekerja pada deskriptor soket dan membiarkan Anda menentukan opsi tertentu untuk operasi yang sebenarnya. Fungsi-fungsi itu sedikit lebih khusus (misalnya, Anda dapat mengatur bendera untuk diabaikanSIGPIPE
, atau untuk mengirim pesan out-of-band ...).Fungsi
read()
/write()
adalah fungsi deskriptor file universal yang bekerja pada semua deskriptor.sumber
recv
dan tidakread
akan mengirimkan data ke pemanggil tetapi juga tidak ada kesalahan. Bagi penelepon, perilakunya sama. Penelepon mungkin bahkan tidak tahu apa-apa tentang datagram (mungkin tidak tahu bahwa ini adalah soket dan bukan file, mungkin tidak tahu bahwa ini adalah soket datagram dan bukan soket aliran). Bahwa datagram tetap tertunda adalah pengetahuan implisit tentang bagaimana tumpukan IP bekerja di kernel dan tidak terlihat oleh pemanggil. Dari perspektif penelepon, mereka masih akan memberikan perilaku yang sama.recv
? Alasan mengaparecv
dan disend
mana diperkenalkan di tempat pertama adalah fakta bahwa tidak semua konsep datagram dapat dipetakan ke dunia aliran.read
danwrite
memperlakukan segala sesuatu sebagai aliran data, apakah itu pipa, file, perangkat (misalnya port serial) atau soket. Namun soket hanya aliran nyata jika menggunakan TCP. Jika menggunakan UDP itu lebih seperti perangkat blok. Tetapi jika kedua belah pihak menggunakannya seperti aliran, itu akan berfungsi seperti aliran dan Anda bahkan tidak dapat mengirim paket UDP kosong menggunakanwrite
panggilan, sehingga situasi ini tidak akan muncul.Per klik pertama di Google
sumber
recv
hanya dapat digunakan pada soket, dan akan menghasilkan kesalahan jika Anda mencoba menggunakannya, katakanSTDIN_FILENO
,.read()
danwrite()
lebih umum, mereka bekerja dengan deskriptor file apa pun. Namun, mereka tidak akan berfungsi di Windows.Anda dapat memberikan opsi tambahan ke
send()
danrecv()
, jadi Anda mungkin harus menggunakannya dalam beberapa kasus.sumber
Saya baru-baru ini memperhatikan bahwa ketika saya menggunakan
write()
soket pada Windows, ia hampir berfungsi (FD yang diteruskanwrite()
tidak sama dengan yang dilewatisend()
; saya biasa_open_osfhandle()
menerima FD yang dilewatiwrite()
). Namun, itu tidak berfungsi ketika saya mencoba mengirim data biner yang menyertakan karakter 10.write()
suatu tempat memasukkan karakter 13 sebelum ini. Mengubahnya menjadisend()
dengan parameter flags 0 memperbaiki masalah itu.read()
bisa memiliki masalah sebaliknya jika 13-10 berturut-turut dalam data biner, tapi saya belum mengujinya. Tapi itu tampaknya menjadi perbedaan lain yang mungkin antarasend()
danwrite()
.sumber
Hal lain di linux adalah:
send
tidak memungkinkan untuk beroperasi pada non-socket fd. Jadi, misalnya menulis di port usb,write
diperlukan.sumber
"Performa dan kecepatan"? Bukankah itu semacam ... sinonim, di sini?
Pokoknya,
recv()
panggilan itu mengambil bendera yangread()
tidak, yang membuatnya lebih kuat, atau setidaknya lebih nyaman. Itu satu perbedaan. Saya tidak berpikir ada perbedaan kinerja yang signifikan, tetapi belum diuji untuk itu.sumber
Di Linux saya juga memperhatikan bahwa:
Memeriksa
man 7 signal
lebih detail.Penggunaan sederhana akan menggunakan sinyal untuk menghindari
recvfrom
pemblokiran tanpa batas.Contoh dari APUE :
sumber