EXtensible Server Core(exsc)の紹介。パート1

画像



みなさん、こんにちは!現在、さまざまなサーバーシステムで数千のクライアントにサービスを提供している多くのサーバーが存在するフレームワークを一般の人々と共有したいと思います。 exsc(EXtensible Server Core)は、Cで記述されたフレームワークであり、1つのアプリケーション内に1つ以上のサーバースレッドを含めることができます。各サーバースレッドは、多数のクライアントにサービスを提供できます。フレームワークは要求/応答モデルで使用できますが、主に、多数のクライアントとの常時接続を維持し、リアルタイムでメッセージを交換するように設計されています。私自身、既製のHelloWorldプロジェクトを取り、それをコンパイルしてすべてがどのように機能するかを確認するのが好きなので、記事の最後にそのようなプロジェクトへのリンクを投稿します。



多くの操作は、特定の接続に対して実行されます。このフレームワークのフレームワーク内で、exsc_excon構造が接続を担当します。この構造には、次のフィールドがあります



。ix-接続インデックス。これは、クライアントが接続したときに解放されていた接続のシリアル番号です。

id-接続識別子。これは一意の接続番号です。インデックスとは異なり、繰り返されません。

addr-クライアントIPアドレス

-接続名。複数の接続に同じ名前で名前を付けることができ、その後、いくつかのメッセージを同じ名前ですべての接続に送信できます(exsc_sendbyname関数を参照)。



カーネルの初期化



カーネルを操作するには、関数を使用してカーネルを初期化する必要があります



void exsc_init(int maxsrvcnt);
      
      





maxsrvcntパラメーターは、アプリケーション内で使用するサーバースレッドの数をカーネルに通知します。



サーバーストリームの開始



次に、関数を使用してサーバーストリームを開始する必要があります



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-サーバーストリームをリッスンするポート。



タイムアウト-サーバースレッドがクライアントからのアクティビティを待機する時間を示します。この間にクライアントがメッセージを送信しなかった場合、サーバースレッドはそのような接続を閉じます。したがって、一定の接続を維持し、このパラメータをたとえば30秒に設定する場合は、10〜15秒ごとにpingメッセージを送信する必要があります。



時間枠-リクエストの実行を許可する時間枠。たとえば、この値が100ミリ秒に設定され、サーバースレッドがユーザーからの現在のすべてのリクエストを10秒で処理した場合、残りの90ミリ秒は他のタスクを実行するプロセッサ。したがって、この値が小さいほど、サーバースレッドは要求を処理する速度は速くなりますが、プロセッサの負荷は大きくなります。



recvbufsize-サーバースレッドが一度に読み取るバッファーのサイズ。



concnt-サーバースレッドが同時に動作する接続の最大数。



newcon-新しいクライアントが接続するたびに機能するコールバック関数。この関数のパラメーターには、接続したクライアントの接続が渡されます。



closeconは、非アクティブな接続が閉じられるたびに実行されるコールバック関数です。この関数のパラメーターは、切断されたクライアントの接続に渡されます。



recvは、クライアントがパケットを送信するときに呼び出されるコールバック関数です。この関数のパラメーターには、データの送信元のクライアントの接続、データへのポインター、およびデータを含むバッファーのサイズが渡されます。



内線-サーバースレッドループの各パスで呼び出されるコールバック関数。この関数は、カーネルの機能を拡張するために作成されています。たとえば、ここでタイマーの処理をリンクできます。 exsc_start



関数 は、サーバースレッドへのハンドルを返します。これは、フレームワークの関数の一部を呼び出すために必要になります。 メッセージ送信この関数は、メッセージ送信を担当します。











void exsc_send(int des, struct exsc_excon *excon, char *buf, int bufsize);
      
      





この関数はスレッドセーフです(どのスレッドからでも呼び出すことができます)。パラメータとして、サーバーストリームのハンドル(exsc_start関数の戻り値として受け取った)、メッセージの送信先の接続、メッセージを含むバッファーへのポインター、およびサイズを渡す必要があります。 バッファの。



また、クライアントのグループにメッセージを送信する機会もあります。これには機能があります



void exsc_sendbyname(int des, char *conname, char *buf, int bufsize);
      
      





これは、メッセージの送信先となる接続の名前である2番目のパラメーターを除いて、exsc_send関数に似ています。



接続名の設定



将来の接続をさらに識別したり、接続に関する情報を保存したり、クライアントのグループにメッセージを送信したりするには、この機能を使用します。



void exsc_setconname(int des, struct exsc_excon *excon, char *name);
      
      





この関数はスレッドセーフです。最初のパラメーターはサーバーストリームのハンドル、2番目のパラメーターは接続自体、3番目のパラメーターはこの接続の名前です。



サーバーストリームを別のサーバーに接続するサーバー



側のロジックでは、データを要求または送信するために別のサーバーに接続する必要がある場合があります。そのようなタスクのために、そのような接続を作成する機能が導入されました。



void exsc_connect(int des, const char *addr, uint16_t port, struct exsc_excon *excon);
      
      





この関数はスレッドセーフです。パラメータとして、サーバーストリームのハンドル、接続する必要のあるサーバーのアドレス、接続する必要のあるサーバーの消費量を渡す必要があります。最後のパラメータとして、接続ポインタを渡します。後でフレームワークの他の関数を呼び出します。接続が行われるのを待つ必要がないことは注目に値します。exsc_connect関数とexsc_send関数を次々に呼び出すことができ、システムは、リモートサーバーに接続できるようになるとすぐにメッセージが送信されることを確認します。



コメント付きのサーバーの例



#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;
}

      
      





結論



exscカーネルは、クライアントとの低レベルの対話のみを行います。これはサーバーシステムの最も重要な要素であり、すべてが構築される基盤であり、それに加えて、接続の管理、メッセージの生成、メッセージの組み立てを担当するより高いレベルを構築する必要があります(おそらくいくつかの段階)。この記事が肯定的な反応を示した場合は、このカーネルに基づいてトップレベルのサーバープログラムを開発するというトピックを開発する第2部が作成されます。



PS

誰かがこのフレームワークの内部ロジックを理解することを決定したり、プロジェクトに適用したりして、バグやボトルネックを見つけた場合は、お知らせください。コミュニティはそのためのものであり、オープンソースプロジェクトに貢献できるすべての人がそうすることができます。



ライブラリへのリンク



例はアーカイブexsc_test_0.zipにあります



All Articles