Dengan SOCK_SEQPACKET unix domain sockets, satu-satunya cara untuk memotong pesan adalah jika buffer yang Anda berikan ke recvmsg() tidak cukup besar (dan dalam hal ini Anda akan mendapatkan MSG_TRUNC).
POSIX mengatakan bahwa soket SOCK_SEQPACKET harus menyetel MSG_EOR di akhir catatan, tetapi soket domain unix Linux tidak.
(Referensi:POSIX 2008 2.10.10 mengatakan SOCK_SEQPACKET harus mendukung catatan, dan 2.10.6 mengatakan batas catatan dapat dilihat oleh penerima melalui bendera MSG_EOR.)
Apa arti 'catatan' untuk protokol tertentu bergantung pada implementasi yang akan ditentukan.
Jika Linux mengimplementasikan MSG_EOR untuk soket domain unix, saya pikir satu-satunya cara yang masuk akal adalah dengan mengatakan bahwa setiap paket adalah catatan tersendiri, jadi selalu setel MSG_EOR (atau mungkin selalu setel saat tidak menyetel MSG_TRUNC), jadi itu akan ' toh jangan informatif.
Saat Anda membaca dokumen, SOCK_SEQPACKET
berbeda dengan SOCK_STREAM
dalam dua cara yang berbeda. Pertama -
Jalur transmisi data berbasis koneksi dua arah yang berurutan, andal, untuk datagram dengan panjang maksimum tetap; konsumen diharuskan untuk membaca seluruh paket dengan setiap panggilan sistem masukan .
--
socket(2)
dari proyek halaman manual Linux
alias
Untuk soket berbasis pesan, seperti SOCK_DGRAM dan SOCK_SEQPACKET, seluruh pesan harus dibaca dalam satu operasi. Jika pesan terlalu panjang untuk dimuat dalam buffer yang disediakan, dan MSG_PEEK tidak disetel dalam argumen flags, kelebihan byte harus dibuang, dan MSG_TRUNC harus disetel dalam anggota msg_flags dari struktur msghdr.
--
recvmsg()
dalam standar POSIX.
Dalam hal ini mirip dengan SOCK_DGRAM
.
Kedua, setiap "datagram" (Linux) / "message" (POSIX) membawa bendera yang disebut MSG_EOR
.
Bagaimanapun Linux SOCK_SEQPACKET
untuk AF_UNIX
tidak mengimplementasikan MSG_EOR
. Dokumen saat ini tidak sesuai dengan kenyataan :-)
Diduga beberapa SOCK_SEQPACKET
implementasi melakukan yang lain. Dan beberapa menerapkan keduanya. Sehingga mencakup semua kemungkinan kombinasi yang berbeda :-)
[1] Protokol berorientasi paket umumnya menggunakan pembacaan tingkat paket dengan semantik pemotongan / pembuangan dan tanpa MSG_EOR. Soket domain X.25, Bluetooth, IRDA, dan Unix menggunakan SOCK_SEQPACKET dengan cara ini.
[2] Protokol berorientasi rekaman umumnya menggunakan pembacaan aliran byte dan MSG_EOR
- tidak ada visibilitas tingkat paket, tidak ada pemotongan / pembuangan. DECNet dan ISO TP menggunakan SOCK_SEQPACKET seperti itu.
[3] Hibrida paket/rekam umumnya menggunakan SOCK_SEQPACKET dengan pemotongan/pembuangan semantik pada level paket, dan paket terminasi rekaman ditandai dengan MSG_EOR. SPX dan XNS SPP menggunakan SOCK_SEQPACKET dengan cara ini.
https://mailarchive.ietf.org/arch/msg/tsvwg/9pDzBOG1KQDzQ2wAul5vnAjrRkA
Anda telah menunjukkan contoh paragraf 1.
Paragraf 2 juga berlaku untuk SOCK_SEQPACKET
seperti yang didefinisikan untuk SCTP. Meskipun secara default menetapkan MSG_EOR
di setiap sendmsg()
. Opsi untuk menonaktifkan ini disebut SCTP_EXPLICIT_EOR
.
Paragraf 3, yang paling konsisten dengan dokumen, tampaknya merupakan kasus yang paling tidak jelas.
Dan bahkan dokumen tidak konsisten dengan dirinya sendiri.
Jenis soket SOCK_SEQPACKET mirip dengan jenis SOCK_STREAM, dan juga berorientasi koneksi. Satu-satunya perbedaan antara jenis ini adalah bahwa batas rekaman dipertahankan menggunakan jenis SOCK_SEQPACKET . Sebuah record dapat dikirim menggunakan satu atau lebih operasi output dan diterima menggunakan satu atau lebih operasi input, tetapi satu operasi tidak pernah mentransfer bagian dari lebih dari satu record. Batas rekaman dapat dilihat oleh penerima melalui flag MSG_EOR dalam flag pesan yang diterima yang dikembalikan oleh fungsi recvmsg(). -- Standar POSIX
Bukan itu gunanya MSG_EOR.
Ingat bahwa API soket adalah abstraksi dari sejumlah protokol yang berbeda, termasuk soket sistem file UNIX, pasangan soket, TCP, UDP, dan banyak protokol jaringan yang berbeda, termasuk X.25 dan beberapa yang sama sekali terlupakan.
MSG_EOR adalah untuk menandakan akhir catatan di mana itu masuk akal untuk protokol yang mendasarinya. Yaitu. itu untuk meneruskan pesan ke lapisan berikutnya di bawah bahwa "ini melengkapi catatan". Ini dapat mempengaruhi misalnya, buffering, menyebabkan pembilasan buffer. Namun jika protokol itu sendiri tidak memiliki konsep "catatan", tidak ada alasan untuk mengharapkan bendera tersebut disebarkan.
Kedua, jika menggunakan SEQPACKET Anda harus membaca seluruh pesan sekaligus. Jika tidak, sisanya akan dibuang. Itu didokumentasikan. Secara khusus, MSG_EOR tidak bendera untuk memberi tahu Anda bahwa ini adalah bagian terakhir dari paket.
Saran:Anda jelas menulis versi non-SEQPACKET untuk digunakan di MacOS. Saya sarankan Anda membuang versi SEQPACKET karena hanya akan menggandakan beban pemeliharaan dan pengkodean. SOCK_STREAM baik untuk semua platform.