2016-08-29 8 views
3

誰かが私のntpの実装に欠けているものを見つけることができますか?NTPの実装C

私は32ビットマイクロコントローラARM Cortex M3をプログラミングしています。 私は、bsdUdpClientとbsdUdpServerを呼び出すwifiSendという3つの関数を持っています。 bsdUdpClientはサーバーにデータを送信し、bsdUdpServerは予約されたNTPポートをリッスンし、NTPサーバーのデータを受信します。

エラーメッセージは一切表示されませんが、受信したバッファは空です。

static void wifiSend(xTimerHandle xTimer){ 

     uint16_t AddrSize = sizeof(SlSockAddrIn_t); 

     if (STATUS_OK != bsdUdpClient(SERVER_PORT, AddrSize)){ 
       printf("Failed to send udp packet\n\r"); 
       assert(false); 
     } 

     if (STATUS_OK != bsdUdpServer(SERVER_PORT, AddrSize)) 
      printf("Failed to receive udp packet\n\r"); 
    } 


    static returnTypes_t bsdUdpClient(uint16_t port, uint16_t AddrSize){ 

      int16_t Status = (int16_t) ZERO; 

      memset(packetBuffer, 0, NTP_PACKET_SIZE); 

      packetBuffer[0] = 0xE3; //0b11100011; // LI, Version, Mode 
      packetBuffer[1] = 0x00;  // Stratum, or type of clock 
      packetBuffer[2] = 0x06;  // Polling Interval 
      packetBuffer[3] = 0xEC; // Peer Clock Precision 
      // 8 bytes of zero for Root Delay & Root Dispersion 
      packetBuffer[12] = 49; 
      packetBuffer[13] = 0x4E; 
      packetBuffer[14] = 49; 
      packetBuffer[15] = 52; 
      Addr.sin_family = SL_AF_INET; 
      Addr.sin_port = sl_Htons((uint16_t) port); 
      Addr.sin_addr.s_addr = sl_Htonl(SERVER_IP); 

      SockID = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, (uint32_t) ZERO); 
      if (SockID < (int16_t) ZERO) 
       return (SOCKET_ERROR); 

      Status = sl_SendTo(SockID, packetBuffer, NTP_PACKET_SIZE *  sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, AddrSize); 


      if (Status <= (int16_t) ZERO) { 
       Status = sl_Close(SockID); 
       if (Status < 0) 
        return (SEND_ERROR); 
       return (SEND_ERROR); 
      } 

      Status = sl_Close(SockID); 
      if (Status < 0) 
       return (SEND_ERROR); 

      return (STATUS_OK); 
    } 

    static returnTypes_t bsdUdpServer(uint16_t port, uint16_t AddrSize){ 

      int16_t Status = (int16_t) ZERO; 

      LocalAddr.sin_family = SL_AF_INET; 
      LocalAddr.sin_port = sl_Htons(5001); 
      LocalAddr.sin_addr.s_addr = 0; 

      SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, (uint32_t) ZERO); 
      if (SockID < 0){ 
       printf("error on sl_Socket\n\r"); 
       return SOCKET_ERROR; 
      } 

      Status = sl_Bind(SockID, (SlSockAddr_t *) &LocalAddr, AddrSize); 
      if (Status < 0){ 
       printf("problem on sl_Bind\n\r"); 
       return SOCKET_ERROR; 
      } 

      Status = sl_RecvFrom(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, &AddrSize); 
      if (Status < (int16_t) ZERO){ 
       printf("error - no bytes received: %d\n\r", (int16_t)Status); 
       return SOCKET_ERROR; 
      } 

      Status = sl_Close(SockID); 
      if (Status < 0) 
       printf("problem on sl_Close\n\r"); 

      uint8_t index3 = packetBuffer[40]; 
      uint8_t index2 = packetBuffer[41]; 
      uint8_t index1 = packetBuffer[42]; 
      uint8_t index0 = packetBuffer[43]; 

      uint16_t highWord = index3 << 16 | index2; 
      uint16_t lowWord = index1 << 16 | index0; 

      uint32_t secondsSince1900 = highWord << 16 | lowWord; 

      printf("Seconds since 1 Janeiro de 1900: %ld\n\r", secondsSince1900); 

      return (STATUS_OK); 

} 
+3

から応答がない場合、ブロッキング状態を避けるためにタイムアウトを追加します。 –

+0

ありがとう@DavidSchwartz。しかし、代わりにSL_SOCK_DGRAMを使用すると、実行中のプログラムはsl_RecvFromから返されることはありません。何か案が? – lmbcerqueira

+2

これはブロック受信です。それは何かを受け取るまでブロックされます。 –

答えて

1

クライアントコードはクエリを送信しますが、ソケットを閉じて応答をリッスンしません。

サーバーコードはクエリを待っていますが、応答を送信しません。

どちらも特に有用なものはありません。ソケットを閉じる前に応答を待ち受けるように、クライアントコードを完成させる必要があります。クエリまたは応答のいずれかが失われた場合には、永久に待機しないようにタイムアウトを使用する必要があることに注意してください。

+0

ありがとう@DavidSchwartz – lmbcerqueira

1

@DavidSchwartzのおかげで、私は現在、実用的な解決策を得ています。

また、受信したパケットから1900年1月1日以降の秒数を抽出しようとしたときに発生したバグを修正しました。

私はこれが誰かを助けることを願っています。改善すべき

:私はSL_SOCK_STREAM`はUDPサーバに属している `とは思わないサーバー

#define NTP_PACKET_SIZE   48 
uint8_t packetBuffer[ NTP_PACKET_SIZE]; 

static returnTypes_t bsdUdpClient(uint16_t AddrSize){ 

    int16_t Status = (int16_t) ZERO; 

    memset(packetBuffer, 0, NTP_PACKET_SIZE); 

    // Initialize values needed to form NTP request 
    packetBuffer[0] = 0xE3; //0b11100011; // LI, Version, Mode 
    packetBuffer[1] = 0x00;  // Stratum, or type of clock 
    packetBuffer[2] = 0x06;  // Polling Interval 
    packetBuffer[3] = 0xEC; // Peer Clock Precision 
    // 8 bytes of zero for Root Delay & Root Dispersion 
    packetBuffer[12] = 49; 
    packetBuffer[13] = 0x4E; 
    packetBuffer[14] = 49; 
    packetBuffer[15] = 52; 

    SockID = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, (uint32_t) ZERO); 
    if (SockID < (int16_t) ZERO) 
     return (SOCKET_ERROR); 

    /*make the request to the server*/ 
    Status = sl_SendTo(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, AddrSize); 

    /*Check if 0 transmitted bytes sent or error condition*/ 
    if (Status <= (int16_t) ZERO) { 
     sl_Close(SockID); 
     return (SEND_ERROR); 
    } 
    else 
     printf("request sent successfully\n\r"); 

    /* receive the reply from the server*/ 
    Status = sl_RecvFrom(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, &AddrSize); 
    if (Status < (int16_t) ZERO){ 
     printf("error - no bytes received: %d\n\r", (int16_t)Status); 
     return SOCKET_ERROR; 
    } 
    else 
     printf("reply received\n\r"); 

    Status = sl_Close(SockID); 
    if (Status < 0) 
     printf("problem on sl_Close\n\r"); 

    uint8_t index3 = packetBuffer[40]; 
    uint8_t index2 = packetBuffer[41]; 
    uint8_t index1 = packetBuffer[42]; 
    uint8_t index0 = packetBuffer[43]; 

    uint16_t highWord = index3 << 8 | index2; 
    uint16_t lowWord = index1 << 8 | index0; 

    uint32_t secondsSince1900 = highWord << 16 | lowWord; 

    printf("Seconds since 1 Janeiro de 1900: %lu\n\r", secondsSince1900); 

    return (STATUS_OK); 

}