BOOST UDP issue

Hello,

I am writing program to use BOOST library for UDP protocol. I have occured 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#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;
}
Last edited on
Here's is an example on how to do it:
https://www.boost.org/doc/libs/1_68_0/doc/html/boost_asio/example/cpp03/timeouts/blocking_udp_client.cpp

run_for is the key, but it is more complex than that because of error checking, you could simplify it using lamdas.

You don't need to call new on the socket, since it is making a memory leak.
Please refer following link for more detail

https://stackoverflow.com/q/53026458/10568640
Well yea, you are sending a packet to something that doesn't exist, I could write an essay on what is wrong with your code, but I am saving you time by just giving you a reference that you should study so you can understand how things work (boost asio is not easy to learn, and the only person who can *really* help you is yourself and the examples).

Where on the internet did you find the native_handle anyways? That is not something that is shown anywhere on boost documentation other than the automatically generated references (because it isn't portable, and it would make more sense to just use the socket api directly in the first place).
Last edited on
As, I have already knew the issue of ICMP unreachable because destination is unreachable.

But you can take reference here for native handle:
https://www.boost.org/doc/libs/1_68_0/doc/html/boost_asio/reference/basic_socket/native_handle.html

Also, for monitoring of file descriptors take reference:
http://man7.org/linux/man-pages/man2/select.2.html

and many more...
https://stackoverflow.com/questions/36401841/asio-udp-socket-receive-failed/36491300
Topic archived. No new replies allowed.