GNU/Linux >> Belajar Linux >  >> Linux

Tujuan sendto address untuk C raw socket?

Menulis ke soket dengan send gagal, memberi tahu saya bahwa saya perlu menentukan alamat.

Gagal, karena send() fungsi hanya dapat digunakan pada terhubung soket (sebagaimana dinyatakan di sini). Biasanya Anda akan menggunakan send() untuk komunikasi TCP (berorientasi koneksi) dan sendto() dapat digunakan untuk mengirim datagram UDP (tanpa koneksi).

Karena Anda ingin mengirim paket "ping", atau lebih tepatnya datagram ICMP, yang jelas tanpa koneksi, Anda harus menggunakan kode sendto() fungsi.

Sepertinya tidak ada bidang tambahan di sendto benar-benar digunakan untuk sebagian besar. Jadi, apakah ada alasan teknis mengapa saya harus menggunakan sendto bukannya send atau hanya pengawasan di API?

Jawaban singkat:

Saat Anda tidak diperbolehkan menggunakan send() , maka hanya tersisa satu pilihan, yang disebut sendto() .

Jawaban panjang:

Ini bukan hanya pengawasan di API. Jika Anda ingin mengirim datagram UDP dengan menggunakan soket biasa (mis. SOCK_DGRAM ), sendto() memerlukan informasi tentang alamat dan port tujuan, yang Anda berikan di struct sockaddr_in , Baik? Kernel akan memasukkan informasi itu ke dalam header IP yang dihasilkan, karena struct sockaddr_in adalah satu-satunya tempat di mana Anda menentukan siapa yang akan menjadi penerima. Atau dengan kata lain:dalam hal ini kernel harus mengambil info tujuan dari struct Anda karena Anda tidak memberikan header IP tambahan.

Karena sendto() tidak hanya digunakan untuk UDP tetapi juga soket mentah, itu harus menjadi fungsi yang kurang lebih "umum" yang dapat mencakup semua kasus penggunaan yang berbeda, bahkan ketika beberapa parameter seperti nomor port pada akhirnya tidak relevan/digunakan.

Misalnya dengan menggunakan IPPROTO_RAW (yang secara otomatis menyiratkan IP_HDRINCL ), Anda menunjukkan niat Anda bahwa Anda ingin membuat header IP Anda sendiri. Demikianlah dua argumen terakhir dari sendto() sebenarnya informasi yang berlebihan, karena sudah termasuk dalam buffer data yang Anda teruskan ke sendto() sebagai argumen kedua. Perhatikan bahwa, meskipun Anda menggunakan IP_HDRINCL dengan soket mentah Anda, kernel akan mengisi alamat sumber dan checksum dari datagram IP Anda jika Anda menyetel kolom yang sesuai ke 0 .

Jika Anda ingin menulis program ping Anda sendiri, Anda juga dapat mengubah argumen terakhir di socket() Anda fungsi dari IPPROTO_RAW ke IPPROTO_ICMP dan biarkan kernel membuat header IP untuk Anda, sehingga Anda tidak perlu khawatir. Sekarang Anda dapat dengan mudah melihat bagaimana kedua sendto() -parameter *dest_addr dan addrlen menjadi signifikan lagi karena itu satu-satunya tempat di mana Anda memberikan alamat tujuan.

Bahasa dan API sudah sangat tua dan telah berkembang seiring waktu. Beberapa API mungkin terlihat aneh dari perspektif saat ini, tetapi Anda tidak dapat mengubah antarmuka lama tanpa merusak banyak kode yang ada. Terkadang Anda hanya perlu membiasakan diri dengan hal-hal yang telah ditentukan/dirancang bertahun-tahun atau beberapa dekade yang lalu.

Semoga itu menjawab pertanyaan Anda.


send() panggilan digunakan ketika soket berada di TCP SOCK_STREAM status terhubung.

Dari halaman manual:

panggilan send() hanya dapat digunakan ketika soket dalam keadaan terhubung (sehingga penerima yang dituju diketahui).

Karena aplikasi Anda jelas tidak terhubung dengan soket lain, kami tidak dapat mengharapkan send() untuk bekerja.


Linux
  1. Perintah Untuk Menentukan Ip Publik?

  2. Pertimbangan untuk bermigrasi ke server cloud Tujuan Umum atau I/O

  3. Mendapatkan Alamat MAC

  1. soket mentah python:Protokol tidak didukung

  2. Membuat soket mentah dengan Python tanpa hak akses root

  3. Mendapatkan alamat gpsd untuk ntpd

  1. ppl – Buku Alamat Baris Perintah Untuk Linux

  2. Bagaimana cara mengirim pesan surat mentah di Linux?

  3. Perintah Shell untuk Mendapatkan Alamat IP?