FrontPage

ソケットサンプル1(Linuxサーバ)

Linux上でサーバとして動作するサンプルを解説する。

C++/ソケットサンプル2(Windowsサーバ・クライアント)
Java/ソケットサンプル

制約

サンプルとして、ホスト名"clove.la"でアクセスできること。
サンプルとして、ポート"57891"でアクセスできること。
コンパイルのコマンドラインは"g++ -Wall seqSv.cpp -lpthread -L/usr/lib"

ファイル名: seqSv.cpp

#include <stdio.h>                                              //  stdioをインクルード                           //
#include <stdlib.h>                                             //  stdlibをインクルード                          //
#include <sys/types.h>                                          //  sys/typesをインクルード                       //
#include <sys/time.h>                                           //  sys/timeをインクルード                        //
#include <sys/socket.h>                                         //  sys/socketをインクルード                      //
#include <netinet/in.h>                                         //  netinet/inをインクルード                      //
#include <unistd.h>                                             //  unistdをインクルード                          //
#include <netdb.h>                                              //  netdbをインクルード                           //
#include <arpa/inet.h>                                          //  arpa/inetをインクルード                       //
#include <string.h>                                             //  stringをインクルード                          //
#include <pthread.h>                                            //  pthreadをインクルード                         //
//#include <semaphore.h>                                        //  semaphoreをインクルード                       //
                                                                //                                                //
#define         BUFF_SIZE_MERE  1024                            //  汎用バッファサイズ                            //
//#define         SV_PORT         4519                            //  使用ポート                                    //
#define         SV_PORT         57891                           //  使用ポート                                    //
#define         MAX_CONNS       19                              //  最大セッション数                              //
                                                                //                                                //
const int       ADDR_SIZE =     sizeof(struct sockaddr_in);     //  sockaddr_inサイズ                             //
                                                                //                                                //
static int      vc_kill_th_sv = 0;                              //  サーバスレッド終了指示                        //
                                                                //                                                //
void* th_sv( void* vd_data );                                   //  サーバ処理                                    //
void* th_cl( void* vd_data );                                   //  クライアント処理                              //
                                                                //                                                //
/* Main *******************************************************//*  起動処理                                      */
int main( void )                                                //  メイン関数                                    //
{                                                               //                                                //
    int rtnCod = 0;                                             //  リターンコード                                //
    pthread_t svid;                                             //  サーバスレッドID                              //
//    pthread_t clid;                                             //  クライアントスレッドID                        //
                                                                //                                                //
    pthread_create( &svid, NULL, th_sv, NULL );                 //  サーバスレッド生成                            //
//    pthread_create( &clid, NULL, th_cl, NULL );                 //  クライアントスレッド生成                      //
//                                                                //                                                //
//    pthread_join( svid, NULL );                                 //  サーバスレッド終了を待つ                      //
//    pthread_join( clid, NULL );                                 //  クライアントスレッド終了を待つ                //
                                                                //                                                //
    getchar();                                                  //  終了確認用                                    //
    vc_kill_th_sv = 1;                                          //  サーバスレッド終了指示                        //
    pthread_join( svid, NULL );                                 //  サーバスレッド終了を待つ                      //
                                                                //                                                //
    return( rtnCod );                                           //  処理終了                                      //
}                                                               //                                                //
//*Main *******************************************************//*  起動処理                                      */
/* Server Thread **********************************************//*  サーバスレッド作成処理                        */
void* th_sv( void* vd_data )                                    //                                                //
{                                                               //                                                //
    int index = 0;                                              //  内部処理判定用                                //
    static int sessionNum = 0;                                  //  セッション数                                  //
    static int sessionIndicator;                                //  セッションID取得用                            //
    int sv_sock;                                                //  サーバ用ソケット                              //
    int cl_sock[MAX_CONNS];                                     //  クライアント用ソケット                        //
    int tmp_sock;                                               //  一時使用ソケット                              //
    int clAddrLen;                                              //  クライアント側アドレス文字列長                //
    int cnt;                                                    //  ループカウンタ                                //
                                                                //                                                //
    fd_set fds;                                                 //  ファイルディスクリプタセット                  //
    fd_set fds_bk;                                              //  ファイルディスクリプタセット(保持用)          //
    struct timeval timeVal;                                     //  タイムアウト時間指定用                        //
                                                                //                                                //
    struct sockaddr_in srcAddr;                                 //  ソースアドレス                                //
//    struct sockaddr_in dstAddr;                                 //  宛先アドレス                                  //
                                                                //                                                //
    char strBuf[BUFF_SIZE_MERE] = "";                           //  文字列用バッファ                              //
                                                                //                                                //
    struct hostent *host;                                       //  ホスト関連情報                                //
    unsigned int** addrRoot;                                    //  ホストアドレス解決用                          //
    int recvBytes;                                              //  受信バイト数確認用                            //
                                                                //                                                //
    host = gethostbyname( "clove.la" );                         //  ホスト関連情報取得                            //
                                                                //                                                //
    memset( cl_sock, 0, sizeof(cl_sock) );                      //  ソースアドレス領域初期化                      //
                                                                //                                                //
    for( ; ; )                                                  //  無限ループ                                    //
    {                                                           //                                                //
        if( NULL == host )                                      //  無効なホストか                                //
        {                                                       //  無効なホストなら                              //
            printf( "unknown host.\n" );                        //  画面表示                                      //
            break;                                              //  処理中止                                      //
        }                                                       //                                                //
                                                                //                                                //
        addrRoot = (unsigned int **)host->h_addr_list;          //  ホストアドレス解決                            //
        if( NULL == *addrRoot )                                 //  アドレス解決に失敗したか                      //
        {                                                       //  アドレス解決に失敗した場合                    //
            printf( "failed to resolve host name.i\n" );        //  画面表示                                      //
            break;                                              //  処理中止                                      //
        }                                                       //                                                //
                                                                //                                                //
        timeVal.tv_sec = 10;                                    //  タイムアウト秒数                              //
        timeVal.tv_usec = 0;                                    //  タームアウトマイクロ秒数                      //
                                                                //                                                //
        memset( &srcAddr, 0, sizeof(srcAddr) );                 //  ソースアドレス領域初期化                      //
                                                                //                                                //
        srcAddr.sin_port = htons( SV_PORT );                    //  ポート指定                                    //
        srcAddr.sin_family = AF_INET;                           //  コネクション型アドレスファミリー              //
        srcAddr.sin_addr.s_addr = htonl( INADDR_ANY );          //  全アドレス許容                                //
                                                                //                                                //
        sv_sock = socket( AF_INET, SOCK_STREAM, 0 );            //  サーバ用ソケット生成                          //
        index = bind( sv_sock, (struct sockaddr *) &srcAddr, ADDR_SIZE ); //  ポート関連付け                      //
        if( -1 == index )                                       //  bindに失敗したか                              //
        {                                                       //  bindに失敗した場合                            //
            printf( "failed to bind.\n" );                      //  画面表示                                      //
            close( sv_sock );                                   //  ソケットクローズ                              //
        }                                                       //                                                //
                                                                //                                                //
        index = listen( sv_sock, MAX_CONNS );                   //  接続待ち                                      //
        if( -1 == index )                                       //  listenに失敗したか                            //
        {                                                       //  listenに失敗した場合                          //
            printf( "time out listening.\n" );                  //  画面表示                                      //
            close( sv_sock );                                   //  ソケットクローズ                              //
        }                                                       //                                                //
                                                                //                                                //
        clAddrLen = sizeof(srcAddr);                            //  アドレス文字列長取得                          //
                                                                //                                                //
        FD_ZERO( &fds_bk );                                     //  FDS初期化                                     //
        FD_SET( sv_sock, &fds_bk );                             //  FDS登録                                       //
                                                                //                                                //
        for( ; ; )                                              //  真・無限ループ                                //
        {                                                       //                                                //
            if( 0 != vc_kill_th_sv )                            //  スレッド終了指示が指示ありか                  //
            {                                                   //  スレッド終了指示が指示ありなら                //
                break;                                          //  真・無限ループを抜けた先で処理終了            //
            }                                                   //                                                //
                                                                //                                                //
            memcpy( &fds, &fds_bk, sizeof(fd_set) );            //  保持していたFDSから複製                       //
            timeVal.tv_sec = 10;                                //  タイムアウト秒数                              //
            timeVal.tv_usec = 0;                                //  タームアウトマイクロ秒数                      //
                                                                //                                                //
            index = select( MAX_CONNS + 1, &fds, NULL, NULL, &timeVal ); //  コネクション通知待ち                   //
            if( 0 == index )                                    //  タイムアウトしたか                            //
            {                                                   //  タイムアウトした場合                          //
                printf( "waiting for clients.\n" );             //  画面表示                                      //
//                memcpy( &fds, &fds_bk, sizeof(fd_set) );        //  保持していたFDSから複製                       //
                continue;                                       //  再select                                      //
            }                                                   //                                                //
                                                                //                                                //
            if( FD_ISSET( sv_sock, &fds ) )                     //  コネクション通知があるか                      //
            {                                                   //  コネクション通知がある場合                    //
//                cl_sock[sessionNum] =                           //  コネクション接続を試行                        //
//                    accept( sv_sock, (struct sockaddr *) &srcAddr, (socklen_t*)ADDR_SIZE ); //                    //
                tmp_sock =                                      //  コネクション接続を試行                        //
//                    accept( sv_sock, (struct sockaddr *) &srcAddr, (socklen_t*)&ADDR_SIZE ); //                   //
                    accept( sv_sock, (struct sockaddr *) &srcAddr, (socklen_t*)&clAddrLen ); //                   //
                if( -1 == tmp_sock )                            //  acceptに失敗したか                            //
                {                                               //  acceotに失敗した場合                          //
                    printf( "time out accepting. sessionNum = %d\n", sessionNum ); //  画面表示                   //
                }                                               //                                                //
                else                                            //  acceptに成功した場合                          //
                {                                               //                                                //
                    if( MAX_CONNS == sessionNum )               //  セッション数が上限に達したか                  //
                    {                                           //  セッション数が上限に達した場合                //
                        printf( "session full.\n\n" );          //  画面表示                                      //
//                        _snprintf_s( strBuf, sizeof(strBuf), 16, "%s", "server busy.\n\n" ); //  メッセージ編集   //
                        snprintf( strBuf, 16, "%s", "server busy.\n\n" ); //  メッセージ編集                      //
                        send( tmp_sock, strBuf, strlen(strBuf), 0 ); //  セッション数最大を通知                   //
                        shutdown( tmp_sock, 2 );                //  ソケットを明示的に停止                        //
                        close( tmp_sock );                      //  ソケットをクローズ                            //
                        sessionNum--;                           //  セッション数をデクリメント                    //
                        continue;                               //  再select                                      //
                    }                                           //                                                //
                                                                //                                                //
                    for( sessionIndicator = 0;                  //  すべてのセッションIDについて                  //
                         MAX_CONNS > sessionIndicator; sessionIndicator++ ) //                                    //
                    {                                           //                                                //
                        if( 0 == cl_sock[sessionIndicator] )    //  ソケットが未接続か                            //
                        {                                       //  ソケットが未接続なら                          //
                            cl_sock[sessionIndicator] = tmp_sock; //  セッションを保持                            //
                            printf( "session ID: %d\n\n", sessionIndicator ); //  画面表示                        //
                            FD_SET( tmp_sock, &fds_bk );        //  FDS登録                                       //
                            sessionNum++;                       //  セッション数をインクリメント                  //
                            printf( "sessions: %d\n\n", sessionNum ); //  画面表示                                //
                            break;                              //  セッションを保持したらループを抜ける          //
                        }                                       //                                                //
                    }                                           //                                                //
                }                                               //                                                //
            }                                                   //                                                //
                                                                //                                                //
            for( cnt = 0; MAX_CONNS > cnt; cnt++ )              //  すべての個別セッションについて                //
            {                                                   //                                                //
                if( FD_ISSET(cl_sock[cnt], &fds) )              //  情報が通知されているか確認する                //
                {                                               //                                                //
                    tmp_sock = cl_sock[cnt];                    //  対象個別ソケット操作用                        //
                    recvBytes = recv( tmp_sock, strBuf, sizeof(strBuf), 0 ); //  メッセージ受信を試行             //
                    printf( "recvBytes = %d.\n\n", recvBytes ); //  画面表示                                      //
                    if( -1 == recvBytes )                       //  受信エラーか                                  //
                    {                                           //                                                //
//                        errInd = WSAGetLastError();             //  エラー番号を保持                              //
//                        if( WSAECONNRESET == errInd )           //  エラー番号がセッションクローズか              //
//                        {                                       //  エラー番号がセッションクローズなら            //
//                            printf( "session closed.\n\n" );    //  画面表示                                      //
//                        }                                       //                                                //
//                        else                                    //  エラー番号がセッションクローズ以外なら        //
//                        {                                       //                                                //
//                            printf( "failed to receive.\n" );   //  画面表示                                      //
//                            printf( "error: %d\n", errInd );    //  画面表示                                      //
//                        }                                       //                                                //
                        printf( "failed to receive.\n" );       //  画面表示                                      //
                        FD_CLR( tmp_sock, &fds_bk );            //  FDSからソケット解放                           //
                        cl_sock[cnt] = 0;                       //  保持ソケットを解放                            //
                        close( tmp_sock );                      //  ソケット解放                                  //
                        sessionNum--;                           //  セッション数をデクリメント                    //
                        continue;                               //  次の個別セッションに進む                      //
                    }                                           //                                                //
                    else if( 0 == recvBytes )                   //  受信バイト数がZEROか                          //
                    {                                           //  受信バイト数がZEROなら                        //
                        printf( "session closed.\n\n" );        //  画面表示                                      //
                        FD_CLR( tmp_sock, &fds_bk );            //  FDSからソケット解放                           //
                        cl_sock[cnt] = 0;                       //  保持ソケットを解放                            //
                        close( tmp_sock );                      //  ソケット解放                                  //
                        sessionNum--;                           //  セッション数をデクリメント                    //
                        continue;                               //  以降のループ処理をスキップ                    //
                    }                                           //                                                //
                    strBuf[recvBytes] = '\0';                   //  文字列終端の付与                              //
                    printf( "server rec: %s\n", strBuf );       //  画面表示                                      //
                                                                //                                                //
                    index = send( tmp_sock, strBuf, strlen(strBuf), 0 ); //  メッセージ送信                       //
                    if( -1 == index )                           //  メッセージ送信に失敗したか                    //
                    {                                           //  メッセージ送信に失敗した場合                  //
                        printf( "failed to send.\n" );          //  画面表示                                      //
                        FD_CLR( tmp_sock, &fds_bk );            //  FDSからソケット解放                           //
                        cl_sock[cnt] = 0;                       //  保持ソケットを解放                            //
                        close( tmp_sock );                      //  ソケット解放                                  //
                        shutdown( tmp_sock, 2 );                //  送受信中止                                    //
                        close( tmp_sock );                      //  ソケット解放                                  //
                        sessionNum--;                           //  セッション数をデクリメント                    //
                        continue;                               //  以降のループ処理をスキップ                    //
                    }                                           //                                                //
                }                                               //                                                //
            }                                                   //                                                //
        }                                                       //                                                //
                                                                //                                                //
        break;                                                  //  ループを抜ける                                //
    }                                                           //                                                //
                                                                //                                                //
    shutdown( sv_sock, 2 );                                     //  送受信中止                                    //
    close( sv_sock );                                           //  ソケット解放                                  //
                                                                //                                                //
    return( vd_data );                                          //  処理終了                                      //
}                                                               //                                                //
//*Server Thread **********************************************//*  サーバスレッド作成処理                        */
/* Client Thread **********************************************//*  クライアントスレッド作成処理                  */
void* th_cl( void* vd_data )                                    //                                                //
{                                                               //                                                //
//    int cnt = 0;                                                //  ループカウンタ                                //
                                                                //                                                //
    return( vd_data );                                          //  処理終了                                      //
}                                                               //                                                //
//*Client Thread **********************************************//*  クライアントスレッド作成処理                  */

動作確認

# g++ -Wall seqSv.cpp -lpthread -L/usr/lib
# ./a.out
session ID: 0

sessions: 1

recvBytes = 7.

server rec: Hello.

recvBytes = 0.

session closed.

修正履歴


課題

クライアントとしての動作は実装していない。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-03-07 (水) 22:41:48 (4524d)