
/*********************************************************************
*   < _GAME_NETWORK.CPP >
**********************************************************************
*   ネットワーク通信に関わるプログラム
**********************************************************************
*                                                   Copyright (C) 2005
*   Programed by Ochi
*********************************************************************/

#include "_speed.h"

#define BUFSIZE     256
#define RECVSIZE    4096
#define TIMEOUT     3

/*********************************************************************
*   接続する
**********************************************************************
*   引数　：無し
*   戻り値：成功か否か(bool)
*********************************************************************/
bool CGame::Connect( void )
{
    char szPartner[256];
    char szPort[32];
    char szTimeOut[32];

    GameInfo = CON_WAIT;
    GetPrivateProfileString( "NetworkSetting", "IPAddress", "", szPartner, sizeof(szPartner), INI_SETUP );
    GetPrivateProfileString( "NetworkSetting", "Port", "", szPort, sizeof(szPort), INI_SETUP );
    GetPrivateProfileString( "NetworkSetting", "WaitingTime", "", szTimeOut, sizeof(szTimeOut), INI_SETUP );
    cSocket.Setting( szPartner, atoi(szPort), SOCK_DGRAM, atoi(szTimeOut) );

    CTimer time;
    time.Start();
    StartConnectThread();
    while( (int)(time.Time()/1000)<atoi(szTimeOut) )
    {
        if ( GameInfo==CONNECT )
        {
            Debug_Send("対戦相手との接続に成功");
            Debug_Send("SNTPサーバと同期中…");
            // 東京大学のサーバと時刻合わせをする
            if( SNTPAdjustTime("eric.nc.u-tokyo.ac.jp") == (LRESULT)false )
            {
                Debug_Send( "時刻の同期に失敗" );
                return false;
            }
            Debug_Send( "SNTPサーバとの同期に成功" );
            Debug_Send( "対戦相手との同期中…" );
            if( cSocket.ReturnObject(CONNECT_TYPE) == SERVER )
            {
                StartServer();
            }
            else
            {
                StartClient();
            }
            Debug_Send( "対戦相手との同期に成功" );
            return true;
        }
        else
        {
            // CPUに負担をかけないため
            Sleep(1000);
        }
    }

    Debug_Send( "接続失敗" );
    DeleteObject( hConnect );
    Message( "CGame::Connect", "対戦者がいないので接続処理を終了しました。", 2 );
    return false;
}

/*********************************************************************
*   スレッドによる接続
**********************************************************************
*   引数　：無し
*   戻り値：終了(bool)
*********************************************************************/
bool CGame::ConnectByThread( void )
{
    if( cSocket.Connect()!=false )
    {
        GameInfo = CONNECT;
    }
    
    return true;
}


/*********************************************************************
*   通信速度を計測する
**********************************************************************
*   引数　：回数(int), バイト(int), 何セット繰り返すか(int)
*   戻り値：成功か否か(bool)
*********************************************************************/
bool CGame::MeasureSpeed( int nSetCount, int nUsrByte, int nUsrCount )
{
    if( GameInfo!=PLAY )
    {
        Message( "CGame::MeasureSpeed", "接続されていないので無効です",2 );
        return false;
    }

    long    n;
    long    n2;
    long    nCount;
    long    nByte;
    long    KeepTime;
    long    Time_ms[100][15];
    char    szBuf[128];
    char    szMessage[RECV_UDP];
    char    szDebug[RECV_UDP];

    GameInfo = MEASURE;
    strcpy( szMessage, "#" );
    cSocket.SendMessage( szMessage ); // スレッドを切る

    while( GameInfo==MEASURE )
    {
        // 待ち時間
        Sleep( 200 );
    }

    if( nSetCount>0 )
    {
        for( n2=0; n2<nSetCount; n2++ )
        {
            nCount=0;
            for( nByte=1; nByte<=16384; nByte=nByte*2 )
            {
                strcpy( szMessage,"" );
                for( n=0; n<nByte; n++ )
                {
                    strcat( szMessage, "#" );
                }

                sprintf( szDebug, "%ld [ms]", cTimer.Time() );
                strcat( szDebug, "function:send()  message:" );
                strcat( szDebug, szMessage );
                //Debug_Send( szDebug );

                KeepTime = cTimer.Time();
                cSocket.SendMessage( szMessage );
                /////////////////////////////////////////////////
                strcpy( szMessage, cSocket.ReceiveMessage() );
                Time_ms[n2][nCount] = cTimer.Time() - KeepTime;
                sprintf( szDebug, "%ld [ms]", cTimer.Time() );
                strcat( szDebug, "function:recv()  message:" );
                strcat( szDebug, szMessage );
                //Debug_Send( szDebug );
                nCount++;
            }
        }

        strcpy( szMessage, "------ 通信速度計測 結果 ------\n\n" );
        for( n2=0; n2<nSetCount; n2++ )
        {
            n = 1;
            for( nCount=0; nCount<15; nCount++ )
            {
                sprintf( szBuf, "%5ld [Byte] : %ld [ms]\n", n, Time_ms[n2][nCount] );
                strcat( szMessage, szBuf );
                n *= 2;
            }
        }
    }
    else
    {
        strcpy( szMessage,"" );
        for( n=0; n<nUsrByte; n++ )
        {
            strcat( szMessage, "#" );
        }
        for( n=0; n<nUsrCount; n++ )
        {
            sprintf( szDebug, "%ld [ms]", cTimer.Time() );
            strcat( szDebug, "function:send()  message:" );
            strcat( szDebug, szMessage );
            //Debug_Send( szDebug );

            KeepTime = cTimer.Time();
            cSocket.SendMessage( szMessage );
            /////////////////////////////////////////////////
            strcpy( szMessage, cSocket.ReceiveMessage() );
            Time_ms[n][0] = cTimer.Time() - KeepTime;
            sprintf( szDebug, "%ld [ms]", cTimer.Time() );
            strcat( szDebug, "function:recv()  message:");
            strcat( szDebug, szMessage );
            //Debug_Send( szDebug );
        }

        strcpy( szMessage, "------ 通信速度計測 結果 ------\n\n" );
        n2 = 0;
        for( n=0; n<nUsrCount; n++ )
        {
            sprintf( szBuf, "%5ld [Byte] : %ld [ms]\n", nUsrByte, Time_ms[n][0] );
            strcat( szMessage, szBuf );
            n2 += Time_ms[n][0];
        }
        sprintf( szBuf, "\n平均 : %d[ms]", n2/nUsrCount );
        strcat( szMessage, szBuf );
    }

    StartRecvThread(); // スレッド立て直し
    Message( "CGame::MeasureSpeed", szMessage, 1 );

    return true;
}

/*********************************************************************
*   メッセージを受信する
**********************************************************************
*   引数　：無し
*   戻り値：終了(bool)
*********************************************************************/
bool CGame::RecvMessage( void )
{
    long    lTime;
    int     nMsgNo;
    int     nMessageType;
    char    szBuf[RECV_UDP];
    char    szBufBuf[RECV_UDP];
    char    szDebug[512];

    int ptrBa[2];           cCards.SetBa( (int*)ptrBa );
    int ptrTefuda[2][8];    cCards.SetTefuda( (int*)ptrTefuda );
    int ptrYama[2][32];     cCards.SetYama( (int*)ptrYama );
    int Judge;
    DWORD thRestart;        // メッセージ受信スレッド
    HANDLE hRestart;        // スレッドのハンドル
    bool bThread=false;     // スレッドが立っているか

    while( 1 )
    {
        strcpy( szBuf,cSocket.ReceiveMessage() );
        if( GameInfo==MEASURE )
        {
            GameInfo = PLAY;
            break;
        }
        if( !strcmp(szBuf,"") )
        {
            Message( "CGame::RecvMessage", "相手のメッセージが受信できないため、終了します。", 2 );
            break;
        }

        sprintf( szDebug, "%ld [ms] ", cTimer.Time() );
        strcat( szDebug, "function:recv()  message: " );
        strcat( szDebug, szBuf );
        Debug_Send( szDebug );

        /***********************************************************
        *   このソフトウェアで有効なメッセージを受信した
        ***********************************************************/
        if( szBuf[0]=='#' )
        {
            /*************************************************
            *   通信時間測定
            *************************************************/
            if( szBuf[1]=='\0' || szBuf[1]=='#' /*|| szBuf[1]==NULL*/ )
            {
                strcpy( szBuf, "#" );
                cSocket.SendMessage( szBuf );
            }
            else
            {
                sscanf( szBuf, "# %s", szBufBuf );  
                /*************************************************
                *   通常の更新
                *************************************************/
                if( !strcmp(szBufBuf,"UPDATE") )
                {
                    sscanf( szBuf, "# %s %ld %d %s", szDebug, &lTime, &nMsgNo, szBufBuf );
                    GameInfo=PAUSE;
                    // OKかNGかを判断する
                    nMessageType=OK;
                    if( fWaitAdmission==true )
                    {
                        // 自分の方が早かった
                        if( lMyTime < lTime )
                        {
                            nMessageType = NG;
                        }
                        else
                        {
                            nMessageType = OK;
                        }
                    }
                    while( cCycleTimer.Time() < (UINT)lPacketCycle )
                    {
                        1+1;
                    }
                    Judge = cCards.Update( szBuf, 0 );
                    SendCards( nMessageType );
                    cCycleTimer.Start();
                    Sleep( lPacketCycle/2 );
                    if( Judge!=0 )
                    {
                        NextGame( Judge, true );
                        break;
                    }
                    GameInfo = PLAY;
                    nMessageNo++;
                    cDraw.DrawCards( cCards, fLButton, nCardNo );
                    InvalidateRect( cDraw.ReturnHWND(), NULL, FALSE );
                }
                /*************************************************
                *   強制終了
                *************************************************/
                else if( !strcmp(szBufBuf,"SHUTDOWN") )
                {
                    cSocket.Close();
                    GameInfo = NOTHING;
                    Message( "CGame::RecvMessage", "強制切断されました。", 2 );
                    break;
                }
                /*************************************************
                *   ポーズ処理
                *************************************************/
                else if( !strcmp(szBufBuf, "PAUSE") )
                {
                    sscanf( szBuf, "# %s %ld %d %s", szDebug, &lTime, &nMsgNo, szBufBuf );
                    GameInfo=PAUSE;
                    /* OKかどうか */
                    nMessageType=OK;
                    if( fWaitAdmission==true )
                    {
                        // 自分の方が早かった
                        if( lMyTime < lTime )
                        {
                            nMessageType = NG;
                        }
                        else
                        {
                            nMessageType = OK;
                        }
                    }
                    while( cCycleTimer.Time() < (UINT)lPacketCycle )
                    {
                        1+1;
                    }
                    cCycleTimer.Start();
                    Judge = cCards.Update( szBuf, 0 );  // カード更新
                    SendCards( nMessageType );          // OK 送信
                    Sleep( lPacketCycle/2 );
                    cDraw.DrawCards( cCards, FALSE, NULL );
                    InvalidateRect( cDraw.ReturnHWND(), NULL, FALSE );
                    if( Judge!=0 )
                    {
                        NextGame( Judge, true );
                        break;
                    }
                    hRestart = CreateThread( NULL, 0, Thread_Restart, NULL, 0, &thRestart );
                    bThread = true;
                }
                /*************************************************
                *   メッセージ了承
                *************************************************/
                else if( !strcmp(szBufBuf,"OK") || !strcmp(szBufBuf,"NG") )
                {
                    // cCycleTimerをとめる
                    if( GameInfo==FIRST )
                    {
                        cCards.Update( szStackMsg, 1 );
                        cDraw.DrawCards( cCards, fLButton, nCardNo );
                        InvalidateRect( cDraw.ReturnHWND(), NULL, FALSE );
                        GameInfo=PLAY;
                    }
                    else if( GameInfo==UPDATE )
                    {
                        cCards.Update( szBuf, 0 );
                        cDraw.DrawCards( cCards, fLButton, nCardNo );
                        InvalidateRect( cDraw.ReturnHWND(), NULL, FALSE );
                        GameInfo=PLAY;
                    }
                    else if( GameInfo==PAUSE )
                    {
                        Restart( NULL );
                    }
                    nMessageNo++;
                }
            }
        }

        fWaitAdmission=false;
        strcpy( szBuf, " " );
    }

    return true;
}

/*********************************************************************
*   カードデータを送信する
**********************************************************************
*   引数　：どの命令で送るか(int)
*   戻り値：送ったデータでゲームが終了するか否か(bool)
*********************************************************************/
bool CGame::SendCards( int MsgFlug )
{
    int     ptrBa[2];           cCards.SetBa( (int*)ptrBa );
    int     ptrTefuda[2][8];    cCards.SetTefuda( (int*)ptrTefuda );
    int     ptrYama[2][32];     cCards.SetYama( (int*)ptrYama );
    bool    b_JudgStop=false;
    char    szBuf[RECV_UDP];
    char    szDebug[512];

    if( MsgFlug==BUF )
    {
        cCards.SetBaBuf( (int*)ptrBa );
        cCards.SetTefudaBuf( (int*)ptrTefuda );
        cCards.SetYamaBuf( (int*)ptrYama );
    }   

    switch( MsgFlug )
    {
    case OK:
        strcpy( szBuf, "# OK " );
        break;
        
    case NG:
        strcpy( szBuf, "# NG " );
        break;

    case INVISIBLE:
        strcpy( szBuf, "# INVISIBLE " );
        break;

    case RESTART:
        strcpy( szBuf, "# RESTART " );
        break;

    default:
        b_JudgStop = cCards.JudgmentStop();
        if( b_JudgStop==true )
        {
            strcpy( szBuf, "# PAUSE " );
        }
        else
        {
            strcpy( szBuf, "# UPDATE " );
        }
        break;
    }

    // "# UPDATE time No ･･･"
    if( MsgFlug==FIRST )
    {
        sprintf( szDebug, "%ld %d ", 0, nMessageNo );
    }
    else 
    {
        sprintf( szDebug, "%ld %d ", cTimer.Time(), nMessageNo );
    }
    strcat( szBuf, szDebug );
    
    for( int n=0; n<22; n++ )
    {
        // 相手の山
        strcat( szBuf, cCards.Decode(ptrYama[1][n]) );
    }
    strcat(szBuf," ");
    for( n=0; n<22; n++ )
    {
        // 自分の山
        strcat( szBuf, cCards.Decode(ptrYama[0][n]) );
    }
    strcat(szBuf," ");

    for( n=0; n<4; n++ )
    {
        // 相手の手札
        strcat( szBuf, cCards.Decode(ptrTefuda[1][n]) );
    }
    strcat(szBuf," ");
    for( n=0; n<4; n++ )
    {
        // 自分の手札
        strcat( szBuf, cCards.Decode(ptrTefuda[0][n]) );
    }
    strcat( szBuf," " );
    // 場
    strcat( szBuf, cCards.Decode(ptrBa[1]) );
    strcat( szBuf, cCards.Decode(ptrBa[0]) );

    strcpy( szStackMsg, szBuf );    // COPY
    cSocket.SendMessage( szBuf );   // SEND
    fWaitAdmission=true;            // 許可待ちのフラグを立てる
    lMyTime = cTimer.Time();        // 送った時間を取得しておく

    sprintf( szDebug, "%ld [ms] ", cTimer.Time() );
    strcat( szDebug, "function:recv()  message: " );
    strcat( szDebug, szBuf );
    //Debug_Send( szDebug );

    return b_JudgStop;
}

/*********************************************************************
*   接続直後のクライアントの処理
**********************************************************************
*   引数　：無し
*   戻り値：終了(bool)
*********************************************************************/
bool CGame::StartClient( void )
{
    int n;
    char szSendMsg[RECV_UDP];

    for( n=0; n<256; n++ )
    {
        szSendMsg[n] = '#';
    }
    szSendMsg[n]='\0';

    for( n=0; n<10; n++ )
    {
        cSocket.ReceiveMessage();
        cSocket.SendMessage( szSendMsg );
    }
    lPacketCycle = atoi( cSocket.ReceiveMessage() );

    // 同期をとるための処理
    int         nStartTime;
    time_t      tTime;
    struct tm*  cTime;

    time(&tTime);
    cTime = localtime(&tTime);

    // 指定時間を受信
    strcpy( szSendMsg, cSocket.ReceiveMessage() );
    nStartTime = atoi(szSendMsg);
    
    // 指定時間になるまで待つ
    while( cTime->tm_sec != nStartTime )
    {
        time(&tTime);
        cTime = localtime(&tTime);
    }

    nMessageNo=0;
    StartRecvThread();
    cCycleTimer.Start();
    cTimer.Start();
    GameInfo = PLAY;
    SetTimer( cDraw.ReturnHWND(), TIMER_ELAPSE, 50, NULL );

    return true;
}

/*********************************************************************
*   接続直後のサーバの処理
**********************************************************************
*   引数　：無し
*   戻り値：終了(bool)
*********************************************************************/
bool CGame::StartServer( void )
{
    int     n;
    long    lSum;
    long    lTime[10];
    char    szSendMsg[RECV_UDP];
    CTimer  cT;

    for( n=0; n<256; n++ )
    {
        szSendMsg[n] = '#';
    }
    szSendMsg[n] = '\0';

    lPacketCycle = -1;
    lSum = 0;
    for( n=0; n<10; n++ )
    {
        cT.Start();
        cSocket.SendMessage( szSendMsg );
        cSocket.ReceiveMessage();
        lTime[n] = cT.Time();
        if( lTime[n] > lPacketCycle )
        {
            lPacketCycle = lTime[n];
        }
        lSum += lTime[n];
    }

    sprintf( szSendMsg, "%ld", lPacketCycle );
    cSocket.SendMessage( szSendMsg );

    // 同期をとるための処理
    int         nStartTime;
    time_t      tTime;
    struct tm*  cTime;

    time(&tTime);
    cTime = localtime(&tTime);
    nStartTime = cTime->tm_sec;
    
    // 往復時間の２倍に3秒を足した時間が、スタート時間とする
    for(n=0; n<(int)((lPacketCycle*2/1000)+3); n++)
    {
        if( nStartTime==59 )
        {
            nStartTime=-1;
        }
        nStartTime++;
    }
    sprintf( szSendMsg, "%d", nStartTime );
    cSocket.SendMessage( szSendMsg );

    // 指定時間になるまで待つ
    while( cTime->tm_sec != nStartTime )
    {
        time(&tTime);
        cTime = localtime(&tTime);
    }
    
    GameInfo = FIRST;
    nMessageNo=0;
    StartRecvThread();
    cCards.SetupCards();
    cTimer.Start();
    cCycleTimer.Start();
    Sleep( (int)lSum/20 );
    SetTimer( cDraw.ReturnHWND(), TIMER_ELAPSE, 50, NULL );
    cGame.SendCards( FIRST );

    return true;
}

/*********************************************************************
*   NTPまたはSNTPサーバに接続し、時刻を同期する
*   注）これはhttp://www.nakka.com/lib/inet/sntpc.htmlにある
*   サンプルプログラムを利用したものです。
**********************************************************************
*   引数　：サーバ名(char*)
*   戻り値：成功か否か(bool)
*********************************************************************/
bool CGame::SNTPAdjustTime( char* szSntpServer )
{
    WORD wVersionRequested;
    int  nErrorStatus;
    WSADATA wsaData;
    char svName[BUFSIZE];                       /* サーバのドメイン名 */
    unsigned short port = 123;                  /* サーバのポート番号 */
    unsigned short local_port = 1024;           /* 受信するポート番号 */
    int soc;                                    /* ソケット（Soket Descriptor） */
    unsigned long serveraddr;                   /* サーバのIPアドレス */
    struct hostent *serverhostent;              /* サーバの情報を指すポインタ */
    struct  sockaddr_in     sockname;           /* ソケットのアドレス */
    struct  sockaddr_in     serversockaddr;     /* サーバのアドレス */
    int sockaddr_Size;                          /* サーバのアドレスのサイズ */
    struct NTP_Packet   NTP_Send;               /* 送信するNTPパケット */
    struct NTP_Packet   NTP_Recv;               /* 受信するNTPパケット */
    fd_set rdps;
    struct timeval waittime;
    int selret;

    time_t Cur_time;                            /* ローカルマシンの時刻 */
    time_t ntp_time;                            /* NTPサーバから取得した時刻 */
    struct tm *lpNewLocalTime;                  /* 現地時刻に変換したNTPサーバの時刻 */
    SYSTEMTIME  Timecall;                       /* ローカルマシンに設定する時刻 */
    float   Splitseconds;

    BOOL sync_flag;                             /* 同期フラグ */
    char *p,*r,*t,wk[8];                        /* 作業用領域 */


    /* 引数のNTPサーバ名を控える */
    strcpy(svName, szSntpServer);
    /* サーバ名にポート番号が指定してあれば、分割する */
    for(p = svName;*p != ':' && *p != '\0';p++);
    if(*p == ':'){
        for(t = p + 1,r = wk;*t != '\0';t++,r++){
            *r = *t;
        }
        *r = '\0';
        port = (unsigned short)atoi(wk);

        *p = '\0';
    }

    /* 同期フラグを立てる */
    sync_flag = TRUE;

    /*----------------------------------------------------------*/
    /*              NTPサーバから時刻を取得する                 */
    /*----------------------------------------------------------*/

    /* WinSockの初期化を行う */
    wVersionRequested = MAKEWORD(1,1);                      /* バージョン 1.1 を要求する */
    nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
    if(atexit((void (*)(void))(WSACleanup))){               /* 終了時にWinSockのリソースを解放するようにしておく */
        Message("CGame::SNTPAdjustTime", "Error: atexit(WSACleanup)失敗", 2);
        return false;
    }
    if(nErrorStatus != 0){
        Message("CGame::SNTPAdjustTime", "Error: WinSockの初期化失敗", 2);
        return false;
    }

    /* UDPモードでsocにソケットを作成します */
    soc = socket(PF_INET,SOCK_DGRAM,0);
    if(soc == INVALID_SOCKET){
        Message("CGame::SNTPAdjustTime", "Error: Socket作成失敗", 2);
        return false;
    }

    /* ソケットのアドレスの構造体にサーバのIPアドレスとポート番号を設定します */
    sockname.sin_family       = AF_INET;                            /* インターネットの場合 */
    sockname.sin_addr.s_addr  = INADDR_ANY;                         /* 自分のIPアドレスを使うようにする */
    sockname.sin_port         = htons((unsigned short)local_port);  /* 受信するポート番号 */
    memset(sockname.sin_zero,(int)0,sizeof(sockname.sin_zero));
    if(bind(soc,(struct sockaddr *)&sockname,sizeof(sockname)) == SOCKET_ERROR){
        Message("CGame::SNTPAdjustTime", "受信ポート番号の指定に失敗", 2);
    }

    /* svNameにドット付き10進数で表したIPアドレスが入っている場合、serveraddrに32bit整数のIPアドレスが返ります */
    serveraddr = inet_addr((char*)svName);
    if(serveraddr == -1) {
        /* サーバ名(svName)からサーバの情報を取得します */
        serverhostent = gethostbyname(svName);
        if(serverhostent == NULL) {
            Message("CGame::SNTPAdjustTime", "Error: ホストアドレス取得失敗", 2);
            /* ソケットを破棄する */
            closesocket(soc);
            return false;
        }else{
            /* サーバの情報からIPアドレスをserveraddrにコピーします */
            serveraddr = *((unsigned long *)((serverhostent->h_addr_list)[0]));
        }
    }

    /* サーバのアドレスの構造体にサーバのIPアドレスとポート番号を設定します */
    serversockaddr.sin_family       = AF_INET;                          /* インターネットの場合 */
    serversockaddr.sin_addr.s_addr  = serveraddr;                       /* サーバのIPアドレス */
    serversockaddr.sin_port         = htons((unsigned short)port);      /* ポート番号 */
    memset(serversockaddr.sin_zero,(int)0,sizeof(serversockaddr.sin_zero));

    /* NTPパケットをSNTP用に初期化する */
    NTP_Send.Control_Word = htonl(0x0B000000);
    NTP_Send.root_delay = 0;
    NTP_Send.root_dispersion = 0;
    NTP_Send.reference_identifier = 0;
    NTP_Send.reference_timestamp = 0;
    NTP_Send.originate_timestamp = 0;
    NTP_Send.receive_timestamp = 0;
    NTP_Send.transmit_timestamp_seconds = 0;
    NTP_Send.transmit_timestamp_fractions = 0;

    /* サーバを指定してNTPパケットを送信する */
    if(sendto(soc,(const char *)&NTP_Send, sizeof( NTP_Send ),0,(struct sockaddr *)&serversockaddr,sizeof(serversockaddr)) == SOCKET_ERROR){
        Message("CGame::SNTPAdjustTime", "Error: サーバへの送信失敗", 2);
        /* ソケットを破棄する */
        closesocket(soc);
        return false;
    }

    /* select関数を使ってタイムアウトを設定する */
    waittime.tv_sec = TIMEOUT;      /* タイムアウト秒数を設定する */
    waittime.tv_usec = 0;
    FD_ZERO(&rdps);
    FD_SET(soc,&rdps);              /* selectするソケットを追加する */

    selret = select(FD_SETSIZE,&rdps,(fd_set *)0,(fd_set *)0,&waittime);
    if(selret == SOCKET_ERROR){                 /* エラーの場合 */
        Message("CGame::SNTPAdjustTime", "Error: サーバからの受信失敗", 2);
        /* ソケットを破棄する */
        closesocket(soc);
        return false;
    }
    if(selret == 0){                /* タイムアウトの場合 */
        fprintf(stderr,"Error: タイムアウトしました\n");
        /* ソケットを破棄する */
        closesocket(soc);
        return false;
    }
    if(FD_ISSET(soc,&rdps) == FALSE){   /* 受信はしたが、指定のソケットではない場合 */
        Message("CGame::SNTPAdjustTime", "Error: サーバからの受信失敗", 2);
        /* ソケットを破棄する */
        closesocket(soc);
        return false;
    }

    /* サーバを指定して受信を行う */
    sockaddr_Size = sizeof(serversockaddr);
    if(recvfrom(soc, (char *)&NTP_Recv, sizeof(NTP_Recv), 0,(struct sockaddr *)&serversockaddr,&sockaddr_Size) == SOCKET_ERROR ){
        Message("CGame::SNTPAdjustTime", "Error: サーバからの受信失敗", 2);
        /* ソケットを破棄する */
        closesocket(soc);
        return false;
    }

    /* ソケットを破棄する */
    closesocket(soc);


    /*----------------------------------------------------------*/
    /*          NTPサーバから取得した時刻を編集する             */
    /*----------------------------------------------------------*/

    /* ローカルマシンの時刻を取得する */
    Cur_time = time(NULL);

    /* NTPサーバから取得した時刻を現地時間に変換する */
    ntp_time = ntohl(NTP_Recv.transmit_timestamp_seconds) - 2208988800;     /* 1970/01/01 からの秒数に変換 */
    lpNewLocalTime = localtime(&ntp_time);
    if(lpNewLocalTime == NULL){
        Message("CGame::SNTPAdjustTime", "Error: 時刻の取得を失敗", 2);
        return false;
    }

    /* 同期フラグが立っている場合は、時刻の同期を行う */
    if(sync_flag == TRUE){
        /* ローカル時刻の計算 */
        Timecall.wYear = lpNewLocalTime->tm_year + 1900;
        Timecall.wMonth = lpNewLocalTime->tm_mon + 1;
        Timecall.wDay = lpNewLocalTime->tm_mday;
        Timecall.wHour = lpNewLocalTime->tm_hour;
        Timecall.wMinute = lpNewLocalTime->tm_min;
        Timecall.wSecond = lpNewLocalTime->tm_sec;

        Splitseconds = (float)ntohl(NTP_Recv.transmit_timestamp_fractions);
        Splitseconds = (float)0.000000000200 * Splitseconds;
        Splitseconds = (float)1000.0 * Splitseconds;
        Timecall.wMilliseconds = (unsigned short)Splitseconds;

        /* ローカル時刻をNTPサーバから取得した時刻に設定する */
        if(!SetLocalTime(&Timecall) == TRUE)
        {
            return false;
        }
    }

    return true;
}