Halo semuanya! Saya ingin berbagi dengan publik kerangka kerja yang saat ini ada banyak server yang melayani ribuan klien di berbagai sistem server. exsc (EXtensible Server Core) adalah kerangka kerja yang ditulis dalam C dan memungkinkan Anda memiliki satu atau lebih utas server dalam satu aplikasi. Setiap utas server mampu melayani sejumlah besar klien. Meskipun framework dapat digunakan dalam model permintaan-respons, framework ini terutama dirancang untuk mempertahankan koneksi konstan dengan sejumlah besar klien dan bertukar pesan secara real time. Karena saya sendiri suka mengambil proyek HelloWorld yang sudah jadi, mengkompilasinya dan melihat bagaimana semuanya bekerja, di akhir artikel saya akan memposting tautan ke proyek semacam itu.
Banyak operasi dilakukan untuk koneksi tertentu. Dalam kerangka kerangka kerja ini, struktur exsc_excon bertanggung jawab atas koneksi tersebut. Struktur ini memiliki bidang berikut:
ix - indeks koneksi. Ini adalah nomor seri koneksi yang gratis pada saat klien terhubung.
id - pengenal koneksi. Ini adalah nomor koneksi unik. Tidak seperti indeks, ia tidak berulang.
addr -
nama alamat IP klien - nama koneksi. Beberapa koneksi dapat diberi nama dengan nama yang sama dan kemudian beberapa pesan dapat dikirim ke semua koneksi dengan nama yang sama (lihat fungsi exsc_sendbyname).
Inisialisasi kernel
Untuk bekerja dengan kernel, kita perlu menginisialisasinya menggunakan fungsi
void exsc_init(int maxsrvcnt);
Parameter maxsrvcnt memberi tahu kernel berapa banyak utas server yang akan kita gunakan dalam aplikasi kita.
Memulai aliran server
Selanjutnya, kita perlu memulai aliran server menggunakan fungsi
int exsc_start(uint16_t port, int timeout, int timeframe, int recvbufsize, int concnt, void newcon(struct exsc_excon excon), void closecon(struct exsc_excon excon), void recv(struct exsc_excon excon, char *buf, int bufsize), void ext());
port - port yang akan mendengarkan aliran server.
batas waktu - menunjukkan berapa lama utas server akan menunggu aktivitas apa pun dari klien. Jika selama ini klien belum mengirim pesan apa pun, maka utas server menutup koneksi tersebut. Oleh karena itu, jika kita ingin menjaga koneksi konstan dan mengatur parameter ini misalnya 30 detik, maka perlu mengirim pesan ping setiap 10-15 detik.
jangka waktu- kerangka waktu yang kami izinkan untuk mengeksekusi permintaan. Misalnya, jika nilai ini disetel ke 100 milidetik dan utas server telah memproses semua permintaan saat ini dari pengguna dalam 10 detik, maka 90 milidetik tersisa ke prosesor untuk melakukan tugas lain. Dengan demikian, semakin kecil nilai ini, semakin cepat server thread akan memproses permintaan, tetapi semakin banyak prosesor akan dimuat.
recvbufsize - ukuran buffer yang akan dibaca oleh thread server dalam satu waktu.
concnt - jumlah koneksi maksimum yang dapat digunakan utas server bekerja secara bersamaan.
newcon- Fungsi panggilan balik yang akan berfungsi setiap kali klien baru terhubung. Parameter dari fungsi ini akan melewati koneksi dari klien yang terhubung.
closecon adalah fungsi panggilan balik yang akan berjalan setiap kali koneksi tidak aktif ditutup. Parameter fungsi ini akan melewati koneksi klien yang terputus.
recv adalah fungsi callback yang akan dipanggil saat klien mengirimkan paket. Parameter fungsi ini akan melewati koneksi klien dari mana data itu berasal, penunjuk ke data dan ukuran buffer dengan data.
ext- fungsi panggilan balik yang akan dipanggil setiap lintasan loop utas server. Fungsi ini dibuat untuk memperluas fungsionalitas kernel. Misalnya, Anda dapat menautkan pemrosesan timer di sini.
Fungsi exsc_start mengembalikan pegangan ke utas server, yang akan diperlukan untuk memanggil beberapa fungsi kerangka kerja.
Mengirim pesan
Fungsi ini bertanggung jawab untuk mengirim pesan.
void exsc_send(int des, struct exsc_excon *excon, char *buf, int bufsize);
Fungsi ini aman untuk thread (Anda dapat memanggilnya dari thread mana pun). Sebagai parameter, Anda harus meneruskannya ke pegangan aliran server (yang kami terima sebagai nilai kembalian dari fungsi exsc_start ), koneksi yang ingin kami kirimi pesan, penunjuk ke buffer dengan pesan dan ukurannya penyangga.
Kami juga memiliki kesempatan untuk mengirim pesan ke sekelompok klien. Ada fungsi untuk ini
void exsc_sendbyname(int des, char *conname, char *buf, int bufsize);
Ini mirip dengan fungsi exsc_send, kecuali untuk parameter kedua, yaitu nama koneksi yang akan dikirimi pesan.
Mengatur nama koneksi
Untuk lebih mengidentifikasi koneksi di masa depan, atau menyimpan beberapa informasi tentangnya dengan koneksi, atau mengirim pesan ke sekelompok klien, gunakan fungsi
void exsc_setconname(int des, struct exsc_excon *excon, char *name);
Fungsi ini aman untuk benang. Parameter pertama adalah pegangan aliran server, parameter kedua adalah koneksi itu sendiri, dan parameter ketiga adalah nama koneksi ini.
Menghubungkan aliran server ke server lain
Terkadang, logika sisi server mengharuskan Anda untuk terhubung ke server lain untuk meminta atau mengirimkan data apa pun. Untuk tugas seperti itu, fungsi diperkenalkan yang membuat koneksi seperti itu.
void exsc_connect(int des, const char *addr, uint16_t port, struct exsc_excon *excon);
Fungsi ini aman untuk benang. Sebagai parameter, kita perlu memberikan pegangan aliran server, alamat server yang perlu kita sambungkan, konsumsi server yang perlu kita sambungkan, dan sebagai parameter terakhir kita meneruskan penunjuk koneksi yang kita dapat nanti memanggil fungsi lain dari kerangka kerja. Perlu dicatat bahwa kita tidak perlu menunggu koneksi terjadi. Kita dapat memanggil fungsi exsc_connect dan exsc_send satu per satu dan sistem akan memastikan bahwa pesan dikirim segera setelah dapat terhubung ke server jarak jauh.
Contoh server dengan komentar
#include <stdio.h>
#include <string.h>
#include "../exnetwork/exsc.h"
int g_des; //
//
void exsc_newcon(struct exsc_excon con)
{
printf("the connection was open %s\n", con.addr);
}
//
void exsc_closecon(struct exsc_excon con)
{
printf("the connection was closed %s\n", con.addr);
}
//
void exsc_recv(struct exsc_excon con, char *buf, int bufsize)
{
char msg[512] = { 0 };
memcpy(msg, buf, bufsize);
printf("receive data from %s\n%s\n", con.addr, msg);
if (strcmp(msg, "say hello") == 0)
{
strcpy(msg, "hello");
exsc_send(g_des, &con, msg, strlen(msg));
}
}
//
void exsc_ext()
{
}
int main()
{
printf("server_test_0 is started\n");
exsc_init(2); //
// 7777
// 30
// 10
// 1024
// 10000
g_des = exsc_start(7777, 30, 10, 1024, 10000, exsc_newcon, exsc_closecon, exsc_recv, exsc_ext);
// ,
// exit ENTER
while (1)
{
const int cmdmaxlen = 256;
char cmd[cmdmaxlen];
fgets(cmd, cmdmaxlen, stdin);
if (strcmp(cmd, "exit\n") == 0)
{
break;
}
}
return 0;
}
Kesimpulan
Kernel exsc hanya melakukan interaksi tingkat rendah dengan klien. Meskipun ini adalah elemen terpenting dari sistem server, fondasi di mana segala sesuatu dibangun, selain itu, Anda perlu membangun tingkat yang lebih tinggi yang akan bertanggung jawab untuk mengelola koneksi, menghasilkan pesan, menyusun pesan (yang mungkin akan masuk beberapa tahap). Jika artikel ini mendapat tanggapan positif, bagian kedua akan ditulis, yang akan mengembangkan topik pengembangan program server tingkat atas berdasarkan kernel ini.
PS
Jika seseorang memutuskan untuk memahami logika internal kerangka kerja ini atau menerapkannya dalam proyek mereka dan menemukan bug atau hambatan di dalamnya, beri tahu kami. Komunitas adalah untuk itu, sehingga setiap orang yang dapat berkontribusi pada proyek sumber terbuka.
Link ke perpustakaan
Contoh terletak di arsip exsc_test_0.zip