Я пишу программу для использования библиотеки BOOST для протокола UDP. Я столкнулся с ошибкой только в Windows, она работает правильно на CentOS 6.9 (Linux) GCC.
Проблема: - Когда я использую функцию send_to для записи данных в сокет для определенного IP-адреса или порта и предполагаю, что IP / PORT не работает, сокет параллельного чтения сообщает нам, что у него есть данные, доступные для чтения. Когда я читаю эти данные, они имеют длину = -1 с использованием собственного сокета.
Пример : предположим, что для этого UDP порт сервера равен 9000, а порт клиента 6000, порт клиента не работает, и принудительно отправляет пакеты дейтаграмм (пакеты UDP) с 9000 (сервер) до 6000 (клиент). Здесь на сокете чтения у нас есть данные и их длина = -1
Здесь, вопрос: почему сокет 9000 (сервер) имеет данные для чтения сразу после записи в сокет, но во время чтения он имеет длину -1.
Итак, если у кого-то есть решение этой проблемы, тогда, пожалуйста, обсудите.
Ниже приведен пример кода:
#include "stdafx.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPCRECATED
#include "WinSock2.h"
#include <boost/asio.hpp>
using boost::asio::ip::udp;
boost::asio::io_service m_ioService;
bool DoesSocketHaveAnyData(udp::socket *m_lpSocket)
{
// set the timeout to UDP_MILLISEC_WAIT_FOR_DATA seconds
struct timeval tv;
tv.tv_sec = 0;
//tv.tv_usec = 1000 * 1000 * 20; // UDP_MILLISEC_WAIT_FOR_DATA;
tv.tv_usec = 1; // UDP_MILLISEC_WAIT_FOR_DATA;
// We'll need to get the underlying native socket for this select call, in order to add a simple timeout on the read:
int nativeSocket = (int)m_lpSocket->native_handle();
fd_set fileDescriptorSet;
FD_ZERO(&fileDescriptorSet);
FD_SET(nativeSocket, &fileDescriptorSet);
bool m_blnCheck = false;
//Wait for message until timeout expires
if (select(nativeSocket + 1, &fileDescriptorSet, NULL, NULL, &tv) == 0)
{
m_blnCheck = false;
}
else
{
if (!FD_ISSET(nativeSocket, &fileDescriptorSet))
{
m_blnCheck = false;
}
else
{
//Issue arise here -> Receice data here, upon checking length -1 (initially, sending data buffer to specific remote endpoint).
//==> Way 1
/*//boost::system::error_code ee;
//size_t tt = m_lpSocket->available(ee);
size_t m_availableNoOfBytes = m_lpSocket->available();
if (m_availableNoOfBytes >= 2) { m_blnCheck = true; }*/
//==> Way 2
struct sockaddr_in src_addr; /* Used to receive (addr,port) of sender */
int src_addr_len; /* Length of src_addr */
int len; /* Length of result from nativeSocket */
char line[BUFSIZ * 2] = { 0 };
src_addr_len = sizeof(src_addr);
len = recvfrom(nativeSocket, line, BUFSIZ * 2, MSG_PEEK /* flags */, (struct sockaddr *) &src_addr, &src_addr_len);
/*printf("Msg from (%u,%u): `%s' (%u bytes)\n", src_addr.sin_addr.s_addr, src_addr.sin_port, line, len);*/
if (len > 0)
{
m_blnCheck = true;
}
else
{
len = recvfrom(nativeSocket, line, BUFSIZ * 2, 0 /* flags */, (struct sockaddr *) &src_addr, &src_addr_len);
}
}
}
return m_blnCheck;
}
int main()
{
int m_uiMyPortNumber = 9000;
try {
//boost::asio::ip::udp::endpoint boostEndPoint(boost::asio::ip::udp::v4(), m_uiMyPortNumber);
udp::endpoint boostEndPoint(boost::asio::ip::address::from_string("192.168.1.117"), m_uiMyPortNumber);
udp::socket *m_lpSocket = new udp::socket(m_ioService, boostEndPoint);
bool blnCheck = false;
do {
m_lpSocket->set_option(boost::asio::socket_base::reuse_address(true));
m_lpSocket->set_option(boost::asio::socket_base::broadcast(true));
m_lpSocket->set_option(boost::asio::socket_base::do_not_route(true));
boost::system::error_code error_obj;
boost::asio::ip::udp::endpoint remote_endpoint(boost::asio::ip::address::from_string("192.168.1.121"), 6000);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Issue arise here -> Sending data buffer to specific remote endpoint. Also, "remote endpoint" is not having opened UDP port.
//=> Way 1: using boost
size_t m_sendto = m_lpSocket->send_to(boost::asio::buffer((char *)"TEST", 4), remote_endpoint, 0, error_obj);
if (error_obj) { return false; }
//=> Way 2: using native socket
/*struct sockaddr_in si_other;
si_other.sin_family = AF_INET;
si_other.sin_port = htons(6000);
#ifdef _WIN32_WINNT 0x0501
si_other.sin_addr.s_addr = inet_addr("192.168.1.121"); //for XP
#else
inet_pton(AF_INET, "192.168.1.121", &inaddr.sin_addr.s_addr); //for Vista or higher
#endif
size_t m_sendto = sendto(m_lpSocket->native_handle(), (char *)"TEST", 4, 0, (struct sockaddr*) &si_other, sizeof(si_other));*/
blnCheck = DoesSocketHaveAnyData(m_lpSocket);
} while (blnCheck == false);
printf("success\n");
}
catch (boost::system::system_error const &e)
{
printf("%s\n", e.what());
}
getchar();
return 0;
}