Клиент не смог отправить запрос на сервер с соединением udp

Я использую Winsock и C ++ для программирования клиента и сервера для возврата смещения от времени NTP и времени ящика. Моя проблема при отладке заключается в том, что клиент не может отправить запрос на сервер. Конкретная функция, которая не работает, это моя sendtoфункция в моем NtpClientThread.cppВот мой сервер:

#pragma once
#include <iostream>
#include "NtpServer.h"#include "stdafx.h"#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <winsock.h>
#include <errno.h>using std::chrono::system_clock;

namespace ntp
{struct sockaddr_in server;
struct sockaddr_storage client;//constructor to create ntp server
NtpServer::NtpServer(u_short portnum, const std::chrono::nanoseconds desiredOffset) : portnum(0), client_length(0), bytes_received(0), current_time(0), desiredOffset(0)
{

WSADATA wsaData;

int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);

if (iResult != 0)
{
throw std::runtime_error("Could not start windows connections.");

}

memset((void *)&server, '\0', sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(portnum);
server.sin_addr.s_addr = htonl(INADDR_ANY);sd = WSASocket(AF_INET, SOCK_DGRAM, 17, NULL, 0, NULL);

if (sd == INVALID_SOCKET)
{
throw std::runtime_error("Could not create socket.");
WSACleanup();

}if (bind(sd, reinterpret_cast<SOCKADDR *>(&server),
sizeof(server)) == -1)
{
throw std::runtime_error("Could not bind name to socket.");
closesocket(sd);
WSACleanup();

}}

NtpServer::~NtpServer()
{
closesocket(sd);
WSACleanup();

}

void NtpServer::getResult()
{
ntp_data ntpData = ntp_data();

//set up timeout with blocking
fd_set fds;
int n;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(sd, &fds);
tv.tv_sec = 10;  // 10 Secs Timeout
tv.tv_usec = 0;
n = select(sd, &fds, NULL, NULL, &tv);
if (n == 0)
{
exit(0);
}

while (1)
{
//client_length = sizeof(client);
int len = (int)sizeof(struct sockaddr_in);

/* Receive bytes from client */
bytes_received = recvfrom(sd, sendBuffer, NTP_PACKET_MAX, 0, (struct sockaddr *)&client, &len);

if (bytes_received == SOCKET_ERROR)
{
throw std::runtime_error("Could not receive datagram.");
closesocket(sd);
WSACleanup();

}
if (bytes_received < NTP_PACKET_MIN)
{
continue;
}/* Check for time request */
if (strcmp(readBuffer, "GET TIME\r\n") == 0)
{
/* Get current time */
system_clock::time_point now = std::chrono::system_clock::now();
auto timepointoffset = (now + desiredOffset).time_since_epoch();
double current_value = std::chrono::duration_cast<std::chrono::duration<double>>(timepointoffset).count();

unpack_ntp(&ntpData, (unsigned char *)readBuffer, bytes_received);
make_packet(&ntpData, NTP_CLIENT, current_value);
pack_ntp((unsigned char *)sendBuffer, NTP_PACKET_MIN, &ntpData);/* Send data back */
if (sendto(sd, sendBuffer,
(int)sizeof(sendBuffer), 0,
(struct sockaddr *)&client, client_length) !=
SOCKET_ERROR)
{
throw std::runtime_error("Error sending datagram.");
closesocket(sd);
WSACleanup();

}
}
}
closesocket(sd);
WSACleanup();

}}

Вот мой код клиента:

NTPClientThread::NTPClientThread(Config config) : stopRequested(false), currentOffset((nanoseconds)0), time_point(NULL) {

WORD wVersionRequested;
wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
//INT hp;try
{
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
throw std::runtime_error("Could not open Windows connection.");
}

/* Open a datagram socket */
sd = WSASocket(AF_INET, SOCK_DGRAM, 17, NULL, 0, NULL);
if (sd == INVALID_SOCKET)
{

WSACleanup();
throw std::runtime_error("Failed to create socket.");
}

/* Clear out server struct */
memset((void *)&server, '\0', sizeof(struct sockaddr_in));/* Set family and port */
server.sin_family = AF_INET;
inet_pton(AF_INET, config.getValue("NtpHost").c_str(), &(server.sin_addr));
server.sin_port = htons(boost::lexical_cast<u_short>(config.getValue("NtpPort")));//clear out client struct
memset((void *)&client, '\0', sizeof(struct sockaddr_in));

/* Set family and port */
client.sin_family = AF_INET;
//inet_pton(AF_INET, config.getValue("NtpHost").c_str(), &(client.sin_addr));
client.sin_addr.s_addr = htonl(INADDR_ANY);
client.sin_port = htons(0);if (bind(sd, reinterpret_cast<SOCKADDR *>(&client)/*result->ai_addr*/,/* result->ai_addrlen*/sizeof(client)) == -1)
{
closesocket(sd);
WSACleanup();
throw std::runtime_error("Failed to bind socket.");

}
ntp_data ntpData = ntp_data();
make_packet(&ntpData, NTP_CLIENT, 0);
pack_ntp((unsigned char *)sendBuffer, NTP_PACKET_MIN, &ntpData);/* Tranmsit data to get time */
server_length = sizeof(struct sockaddr_in);
if (sendto(sd, (const char *)sendBuffer, sizeof(sendBuffer), 0, (struct sockaddr *)&server/*result->ai_addr*/, server_length/*result->ai_addrlen*/) == -1)
{
throw std::runtime_error("Failed to send request to server.");

}

int bytes_received = recvfrom(sd, (char *)&current_time, (int)sizeof(current_time), 0, (struct sockaddr *)&server, &server_length);
/* Receive time */
if (bytes_received < 0)
{
throw std::runtime_error("Failed to recieve data from server.");

}
if (bytes_received < NTP_PACKET_MIN)
{
throw std::runtime_error("Received bad responde from server.");
}unpack_ntp(&ntpData, current_time, server_length);typedef duration<double, std::ratio<1>>d_seconds;
d_seconds since_epoch_full(ntpData.transmit);
auto since_epoch = duration_cast<system_clock::duration> (since_epoch_full);

system_clock::time_point ntpTime(since_epoch);
system_clock::time_point boxTime = system_clock::now();

currentOffset = ntpTime - boxTime;

}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}

0

Решение

Посмотрите на документация inet_pton. inet_pton преобразовать строку, представляющую IP-адрес, в двоичный IP-адрес. Он не разрешает имена, поэтому не будет работать с именем хоста, например localhost, который должен быть решен.

Вы должны использовать определенную функцию для разрешения имени, например getaddrinfo (рекомендуется) или gethostbyname (Устарел).

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]