Pelayan Echo Ringkas
Hidangkan ramai klien serentak.
Pelayan Echo Ringkas ialah pelajaran C Academy percuma di CoddyKit. Ini ialah pelajaran 4 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran C Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus C Academy merangkumi sejumlah 4 pelajaran.
Perkara yang Kita Bina
Pelayan gema menerima sambungan TCP dan menghantar semula apa sahaja bait yang dihantar oleh klien. Ia ialah "hello world" bagi pengaturcaraan rangkaian.
Kita akan membinanya menggunakan epoll supaya satu utas dapat melayan banyak klien serentak. Komponennya ialah: soket pendengar, gelung epoll dan pengendalian baca-kemudian-tulis bagi setiap klien.
Mencipta Soket Pendengar
Mulakan dengan socket() untuk titik akhir TCP IPv4. Tiga parameternya ialah AF_INET, SOCK_STREAM dan protokol 0.
Ini mengembalikan deskriptor fail yang akan kita ikat, tetapkan kepada mod tanpa sekatan dan akhirnya daftarkan dengan epoll. Semak nilai -1 bagi setiap panggilan sistem.
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd == -1) { perror("socket"); exit(1); }Menggunakan Semula Alamat
Sebelum mengikat alamat, tetapkan SO_REUSEADDR dengan setsockopt(). Ini membolehkan pelayan dimulakan semula dan diikat semula pada port yang sama tanpa menunggu keadaan TIME_WAIT tamat.
Tanpanya, pemulaan semula yang pantas sering gagal dengan EADDRINUSE, sesuatu yang mengecewakan semasa pembangunan.
int yes = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);Mengikat pada Port
Isikan struct sockaddr_in dengan keluarga, port dan alamat. Gunakan htons() untuk port dan INADDR_ANY untuk mendengar pada semua antara muka.
Kemudian panggil bind() untuk mengikat soket pada alamat tersebut. htons menukar susunan bait hos kepada susunan bait rangkaian, dan penukaran ini diperlukan.
struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(8080);
bind(listen_fd, (struct sockaddr*)&addr, sizeof addr);Mendengar dan Mengaktifkan Mod Tanpa Sekatan
Panggil listen() untuk menjadikan soket pasif dan menetapkan baris gilir bagi sambungan yang menunggu. SOMAXCONN meminta nilai maksimum sistem.
Kemudian tukar soket kepada mod tanpa sekatan supaya accept() tidak pernah menghentikan gelung peristiwa. Kini soket itu sedia untuk didaftarkan dengan epoll.
listen(listen_fd, SOMAXCONN);
set_nonblocking(listen_fd);Mendaftarkan Pendengar
Cipta instans epoll dan tambahkan soket pendengar dengan EPOLLIN. Peristiwa boleh dibaca di sini bermaksud klien baharu sedang menunggu untuk diterima.
Kita menyimpan fd dalam data.fd supaya kita dapat mengenal pasti pendengar di dalam gelung.
int epfd = epoll_create1(0);
struct epoll_event ev = { .events = EPOLLIN, .data.fd = listen_fd };
epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev);Menerima Klien
Apabila pendengar boleh dibaca, ulangi accept() sehingga EAGAIN. Setiap soket klien baharu ditetapkan kepada mod tanpa sekatan dan didaftarkan untuk EPOLLIN.
Mulai saat ini, epoll akan memberitahu kita setiap kali klien menghantar data yang boleh kita gema semula.
int c = accept(listen_fd, NULL, NULL);
if (c != -1) {
set_nonblocking(c);
struct epoll_event cev = { .events = EPOLLIN, .data.fd = c };
epoll_ctl(epfd, EPOLL_CTL_ADD, c, &cev);
}Logik Gema
Bagi klien yang sedia, gunakan recv() untuk membaca ke dalam penimbal. Jika anda menerima bait, hantar bait yang sama terus kembali dengan send().
Operasi baca-kemudian-tulis yang mudah ini ialah gema. Dalam persekitaran sebenar, anda perlu menimbal bait yang belum dihantar, tetapi untuk demonstrasi ini kita menganggap balasan kecil itu muat dalam penimbal penghantaran.
char buf[4096];
ssize_t r = recv(fd, buf, sizeof buf, 0);
if (r > 0) {
send(fd, buf, r, 0);
}Mengesan Pemutusan Sambungan
Nilai pulangan 0 daripada recv() bermaksud klien telah melakukan penutupan teratur. Nilai pulangan negatif bersama apa-apa selain EAGAIN ialah ralat sebenar.
Dalam kedua-dua keadaan, buang deskriptor daripada epoll dan close() deskriptor itu untuk membebaskan sumber serta menghentikan peristiwa seterusnya.
if (r == 0 || (r < 0 && errno != EAGAIN)) {
epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
close(fd);
}Gelung Lengkap
Gabungkan bahagian-bahagiannya: tunggu peristiwa, tentukan sama ada deskriptor itu pendengar atau klien, kemudian bertindak sewajarnya.
Gelung padat ini ialah pelayan gema serentak yang berfungsi sepenuhnya. Satu utas, banyak klien, tanpa utas berasingan bagi setiap sambungan.
for (;;) {
int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
for (int i = 0; i < n; i++) {
if (events[i].data.fd == listen_fd) accept_clients();
else echo_or_close(events[i].data.fd);
}
}Menguji dan Langkah Seterusnya
Kompil pada Linux dan sambung dengan nc localhost 8080; apa sahaja yang anda taip akan dihantar semula. Buka beberapa terminal untuk membuktikan keserentakan.
Untuk menjadikannya lebih kukuh: timba data yang dihantar sebahagian, kendalikan EPOLLOUT, tukar kepada EPOLLET dengan pengosongan sepenuhnya dan kendalikan EPOLLRDHUP untuk penutupan separa.
Semakan Pantas
Uji pemahaman anda tentang aliran pelayan gema.
Ringkasan
Anda telah membina pelayan gema epoll: cipta, tetapkan SO_REUSEADDR, ikat, dengar, dan jadikan tidak menyekat. Daftarkan pendengar, terima klien dalam gelung, dan gema menggunakan recv()/send().
Kendalikan nilai pulangan 0 sebagai pemutusan sambungan dan tutup dengan kemas. Daripada rangka asas ini, anda boleh mengembangkan pelayan rangkaian satu utas berprestasi tinggi.
Pelajari C dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 39
- Pelajaran
- 144
Soalan Lazim
Adakah pelajaran “Pelayan Echo Ringkas” percuma?
Ya — teks penuh “Pelayan Echo Ringkas” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus C Academy, tingkat taraf kepada CoddyKit PRO. Kursus C Academy merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Pelayan Echo Ringkas”?
Hidangkan ramai klien serentak. Anda berlatih C Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan C Academy?
Tiada pengalaman terdahulu diperlukan. Pembelajaran C Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 4 daripada 4.
Berapa lamakah pelajaran “Pelayan Echo Ringkas” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran C Academy ini?
Ya. Setiap pelajaran C Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- I/O Menyekat berbanding Tidak Menyekat
- Menyediakan epoll
- Gelung Peristiwa
- Pelayan Echo Ringkas