I am writing program to use BOOST library for UDP protocol. I have occurred with an error on windows only, it is working correct on CentOS 6.9 (Linux) GCC.
Issue is - When I use send_to function to write data on socket for specific IP or Port and suppose that IP/PORT is not working, then parallel reading socket inform us that it has data available for reading. When I read that data then it has length = -1 using native socket.
Example: Suppose for this UDP, Server PORT is 9000 and client PORT 6000, client port is not working, and forcefully send datagram packets (UDP packets) from 9000 (Server) to 6000 (client). Here, on read socket we have data and its length = -1
Here, question: why 9000 (Server) socket have data for reading just after write to socket, but during read it has -1 length.
So, if anyone have solution of this issue then please discuss.
Below is the sample code:
#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;
}