GNU/Linux >> Belajar Linux >  >> Linux

Periksa koneksi terbuka atau tertutup? (dalam C di Linux)

Saya menggunakan send() alih-alih write() yang tidak menangani sinyal :

bzero(buffer, MAX_SIZE_BUFFER);
n = read(sockfd, buffer, MAX_SIZE_BUFFER - 1);
printf("after read%d\n", n);
if (n <= 0)
{
    break;
}
n2 = send(newsockfd, buffer, n, MSG_NOSIGNAL);
if (n2 == -1)
{
    close(sockfd);
    close(newsockfd);
    return;
}
if (n2 != n)
{
    break;
}

Pemrograman soket bisa agak rumit, karena Anda sering kali tidak mengetahui bahwa telah terjadi kesalahan hingga beberapa waktu kemudian.

Misalnya, jika mesin yang Anda tuju mati secara tidak normal, panggilan tulis mungkin berhasil (karena Anda dapat menulis ke buffer OS internal Anda), namun gagal selama panggilan tertutup.

Kecuali jika Anda memiliki cara lapisan aplikasi untuk memverifikasi bahwa soket aktif (yaitu, mengirim pesan dan meminta tanggapan dalam jangka waktu tertentu), Anda tidak memiliki cara untuk mengetahuinya. Jika Anda menggunakan protokol standar, sesuatu mungkin sudah ada untuk menangani kesalahan.

Jadi jawaban singkatnya adalah Anda perlu memeriksa pengembalian kesalahan dari hampir setiap panggilan yang menyentuh soket ( baca, tulis, tutup, dll ... ).


Cara untuk memeriksa apakah Anda dapat menulis ke soket, secara mengejutkan, mencoba dan menulis ke sana :-)

Jika soket telah ditutup, Anda akan mendapatkan -1 mengembalikan kode dari write dan Anda dapat memeriksa errno untuk melihat apa masalahnya.

Jika soket masih valid tetapi Anda tidak dapat menulis data apa pun saat ini, write akan mengembalikan 0. read call juga berperilaku serupa, mengembalikan -1 jika ada masalah.

Pada dasarnya, untuk write :

  • jika Anda mendapatkan kembali -1 , ada masalah dan Anda harus memeriksa errno untuk melihat apakah dapat dipulihkan atau fatal.
  • Jika Anda mendapatkan kembali 0 , maka Anda tidak dapat menulis apa pun saat ini (mungkin backlog jaringan atau masalah lain tetapi jelas tidak (belum) fatal).
  • Jika Anda mendapatkan nilai kurang dari yang Anda inginkan, maka beberapa dari data telah dikirim. Sesuaikan pointer Anda sehingga Anda dapat mencoba mengirim sisanya di siklus berikutnya. Jangan jangan menganggap nilai pengembalian positif berarti seluruh blok telah dikirim.
  • Jika Anda mendapatkan kembali nomor yang sama dengan jumlah byte yang Anda coba kirim, seluruh buffer telah diterima untuk pengiriman.
  • Jika Anda mendapatkan kembali lebih dari apa yang Anda minta untuk dikirim, kirim email ke pengembang kernel dengan beberapa komentar tajam. Linus dkk akan menyukainya :-)

Perbarui: Seperti yang ditunjukkan kafe di komentar, saya lupa memperhitungkan penanganan sinyal. Anda harus mengabaikan sinyal pipa yang rusak atau write akan gagal secara internal dengan menaikkan sinyal itu.

Anda dapat melakukannya dengan memasukkan:

struct sigaction new_actn, old_actn;
new_actn.sa_handler = SIG_IGN;
sigemptyset (&new_actn.sa_mask);
new_actn.sa_flags = 0;
sigaction (SIGPIPE, &new_actn, &old_actn);

sebelum mulai menggunakan fungsi soket. Anda kemudian dapat menggunakan:

sigaction (SIGPIPE, &old_actn, NULL);

untuk memulihkan penanganan sinyal sebelumnya.


Linux
  1. periksa semua soket dibuka di OS linux

  2. Bagaimana Cara Menambahkan File di C, menggunakan Open in O_APPEND Mode di linux?

  3. Cara menentukan waktu koneksi soket di Linux

  1. Cara Memeriksa Mendengarkan / Membuka Port dengan Netstat di Linux

  2. Cara Memeriksa Port Terbuka pada Sistem Linux Jarak Jauh

  3. Periksa apakah port terbuka atau tertutup di server Linux?

  1. Periksa batas FD terbuka untuk proses tertentu di Linux

  2. papan klip linux baca/tulis dalam C

  3. Bagaimana cara menulis driver perangkat blok linux userspace?