如何从NTP服务器接收数据? [英] How do I receive data from NTP server?

查看:308
本文介绍了如何从NTP服务器接收数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道为什么发送数据是48个字节010,0,0 ...,有人可以解释吗?问题是缓冲接收到的数据,我不知道他应该有多大,即使我接收到数据,也要如何从中获取正常时间?

I have no idea why send data is 48 bytes 010,0,0..., someone can explain? the problem is buffer for data received, I don't know how big he should be, and even if I receive data, how to make normal time from it?

代码:

#include <iostream>

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define WIN32_MEAN_AND_LEAN

#include <winsock2.h>
#include <windows.h>

#include <time.h>



using namespace std;

class HRException
{
public:
    HRException() :
        m_pMessage("") {}
    virtual ~HRException() {}
    HRException(const char *pMessage) :
        m_pMessage(pMessage) {}
    const char * what() { return m_pMessage; }
private:
    const char *m_pMessage;
};

const int  REQ_WINSOCK_VER = 2; // Minimum winsock version required
const char DEF_SERVER_NAME[] = "0.pl.pool.ntp.org";
const int  SERVER_PORT = 123;
const int  TEMP_BUFFER_SIZE = 128;

const char msg[48] = { 010,0,0,0,0,0,0,0,0 };


// IP number typedef for IPv4
typedef unsigned long IPNumber;

IPNumber FindHostIP(const char *pServerName)
{
    HOSTENT *pHostent;

    // Get hostent structure for hostname:
    if (!(pHostent = gethostbyname(pServerName)))
        throw HRException("could not resolve hostname.");

    // Extract primary IP address from hostent structure:
    if (pHostent->h_addr_list && pHostent->h_addr_list[0])
        return *reinterpret_cast<IPNumber*>(pHostent->h_addr_list[0]);

    return 0;
}

void FillSockAddr(sockaddr_in *pSockAddr, const char *pServerName, int portNumber)
{
    // Set family, port and find IP
    pSockAddr->sin_family = AF_INET;
    pSockAddr->sin_port = htons(portNumber);
    pSockAddr->sin_addr.S_un.S_addr = FindHostIP(pServerName);
}

bool RequestHeaders(const char *pServername)
{
    SOCKET      hSocket = INVALID_SOCKET;
    char        tempBuffer[TEMP_BUFFER_SIZE];
    sockaddr_in sockAddr = { 0 };
    bool        bSuccess = true;

    try
    {
        // Lookup hostname and fill sockaddr_in structure:
        cout << "Looking up hostname " << pServername << "... ";
        FillSockAddr(&sockAddr, pServername, SERVER_PORT);
        cout << "found.\n";

        // Create socket
        cout << "Creating socket... ";
        if ((hSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
            throw HRException("could not create socket.");
        cout << "created.\n";

        // Connect to server
        cout << "Attempting to connect to " << inet_ntoa(sockAddr.sin_addr)
            << ":" << SERVER_PORT << "... ";
        if (connect(hSocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr)) != 0)
            throw HRException("could not connect.");
        cout << "connected.\n";

        cout << "Sending request... ";

        // send request part 1
        if (send(hSocket, msg, sizeof(msg) , 0) == SOCKET_ERROR)
            throw HRException("failed to send data.");



        cout << "request sent.\n";

        cout << "Dumping received data...\n\n";
        // Loop to print all data

        recv(hSocket, tempBuffer, sizeof(tempBuffer), 0);  // <-- the problem
    ///
       //part where we take time out of tempBuffer

    ///







    }
    catch (HRException e)
    {
        cerr << "\nError: " << e.what() << endl;
        bSuccess = false;
    }

    if (hSocket != INVALID_SOCKET)
    {
        closesocket(hSocket);
    }
    return bSuccess;
}

int main(int argc, char* argv[])
{

    int iRet = 1;
    WSADATA wsaData;

    cout << "Initializing winsock... ";

    if (WSAStartup(MAKEWORD(REQ_WINSOCK_VER, 0), &wsaData) == 0)
    {
        // Check if major version is at least REQ_WINSOCK_VER
        if (LOBYTE(wsaData.wVersion) >= REQ_WINSOCK_VER)
        {
            cout << "initialized.\n";

            // Set default hostname:
            const char *pHostname = DEF_SERVER_NAME;

            // Set custom hostname if given on the commandline:
            if (argc > 1)
                pHostname = argv[1];

            iRet = !RequestHeaders(pHostname);
        }
        else
        {
            cerr << "required version not supported!";
        }

        cout << "Cleaning up winsock... ";

        // Cleanup winsock
        if (WSACleanup() != 0)
        {
            cerr << "cleanup failed!\n";
            iRet = 1;
        }
        cout << "done.\n";
    }
    else
    {
        cerr << "startup failed!\n";
    }
    int x;
    cin >> x;

    return iRet;
}

大部分代码来自madwizard.org

Most part of code is from madwizard.org

推荐答案

好吧,代码的主要部分:

Ok it works, main part of code:

        const char msg[48] = { 010,0,0,0,0,0,0,0,0 };

        if (send(hSocket, msg, sizeof(msg) , 0) == SOCKET_ERROR)
            throw HRException("failed to send data.");



        cout << "request sent.\n";

        cout << "Dumping received data...\n\n";


        char   tempBuffer[1024];
        int bytes =  recv(hSocket, tempBuffer, sizeof(tempBuffer), 0);  
        cout << "bytes received: " << bytes << endl;

        time_t tmit;
        tmit = ntohl(((time_t*)tempBuffer)[4]);
        tmit -= 2208988800U;

        cout << ctime(&tmit);

不知道为什么我们发送的数据是

No idea why data that we send is

msg[48] = { 010,0,0,0,0,0,0,0,0 };

为什么接收到的数据包含很多数字?例如,如果将代码更改为

and why received data contains many numbers? for example if change code to

tmit = ntohl((((time_t *)tempBuffer)[6]);

我会得到日期2008y,为什么?

I will get date 2008y, why?

请问为什么这么多缺点?,仍在等待解释:D

Guys why so many minuses?, still waiting for an explanation :D

这是整个代码 http://pastebin.com/Sv3ERGfV ,不要忘记链接ws2_32.lib

Here's whole code http://pastebin.com/Sv3ERGfV , dont forget to link ws2_32.lib

这篇关于如何从NTP服务器接收数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆