Packets sent from QUdpSocket are not seen in Wireshark - c++

I'm trying to see my outgoing UDP traffic in Wireshark.
I created new socket and bind it to my QHostAddress::LocalHost with no errors. I then sent some data writeDatagram and the return value is correct, but I see no outgoing traffic in Wireshark.
// create a socket called from init()
socket = new QUdpSocket(this);
bool ret = socket->bind(QHostAddress::LocalHost, 47000);
if (ret == false)
{
printf("failed to bind socket\n");
}
// create and sent some data called from send()
QHostAddress addr("192.168.5.12"); // addr of my other computer
qint64 size = socket->writeDatagram(QByteArray("udp data"),addr,47000);
printf("sent %d\n",size); // correct size sent 8
I checked the firewall setting and it's the same result if I turn it off.

SOLVED by changing the QHostAddress from localhost to assigned router address.

Related

UDP socket select() returns 1 without delay (timeout) under some conditions

I fallen into problem during development of my client application.
I want to use non-blocking UDP sockets in my application to communicate with a server. I am using winsock2 library on Windows.
But... For some reason I have strange behavior of select() function under some conditions:
Socket don't have bound address and port (it is client-side socket, so it don't need it).
Before select() I send data to my local address and some port with sendto call.
For example: 192.168.1.2
Under these conditions select() instantly (without even waiting for timeout) returns 1. Like I have some packet ready to receive.
But if call recvFrom then it will sure return -1.
If I send my packets from client to any other address (which is not my address on LAN) then select() works as intended.
Also select() works as intented if don't send any packets to any address before calling select().
Socket initialization method:
bool CUdpSocket::initialize()
{
_handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
... error processing code, returns false if error...
}
Method which uses select(). This method works fine for server socket (with bound address and port).
bool CUdpSocket::waitData(s32 timeout_ms)
{
fd_set readset;
int result;
struct timeval tv;
// Initialize the set.
FD_ZERO(&readset);
FD_SET(_handle, &readset);
// Initialize time out struct.
tv.tv_sec = 0;
tv.tv_usec = timeout_ms * 1000;
result = select(_handle + 1, &readset, NULL, NULL, &tv);
// Timeout with no data.
if (result == 0) {
return false; // Get out of here!
}
// Error.
if (result < 0) {
// TODO: Maybe throw exception or do something.
return false;
} else if (!FD_ISSET(_handle, &readset)) {
return false; // No data!
}
// There is some data!
return true;
}
If you send a packet from an unbound UDP socket, the OS will pick an usused port for you and bind the socket to that port -- the UDP protocol requires that the sending port have an address to send from.
So if the packet you're sending results in a response, then it makes perfect sense for the select to return 1 -- that's the response to the packet you sent.

How to receive a UDP broadcast sent to 255.255.255.255 using boost asio?

I have written a device discovery program that can run in client or server mode. In client mode it sends a UDP broadcast packet to 255.255.255.255 on port 30000 and then listens for responses on port 30001. In server mode it listens for a UDP broadcast on port 30000 and sends a UDP broadcast packet to 255.255.255.255 on port 30001 in response.
When I run this program on 2 devices with IP addresses 192.168.10.61 and 192.168.10.62 it all works perfectly. The whole point of this program is to allow devices with unknown IP addresses to discover one another so long as they are connected to the same physical network. So to test that, I changed the IP address of the first device to something random like 12.34.56.42/255.255.240. And now it stops working.
Using tcpdump on the 192.168.10.62 machine I can see that the UDP packet from the 12.134.56.42 machine was received:
# tcpdump -i eth0 port 30000 -c 1 -v
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:38:02.552427 IP (tos 0x0, ttl 64, id 18835, offset 0, flags [DF], proto UDP (17), length 49)
12.34.56.42.56815 > 255.255.255.255.30000: UDP, length 21
1 packet captured
6 packets received by filter
0 packets dropped by kernel
but my discovery program no longer receives it. This is the code I am using to receive the UDP broadcast packets:
int WaitForPacket(uint16_t portNum, vector<char>& udpBuf, udp::endpoint& remoteEndpoint, const chrono::milliseconds timeout)
{
io_service ioService;
udp::socket socket(ioService, udp::endpoint(boost::asio::ip::address_v4::any(), portNum));
socket.set_option(socket_base::broadcast(true));
boost::system::error_code error;
int numBytes = receive_from(socket, buffer(udpBuf), remoteEndpoint, error, timeout);
if (error && error != error::message_size && error != error::timed_out)
{
printf("Got error: %s\n", error.message().c_str());
return -1;
}
return numBytes;
}
/*
* The boost asio library does not provide a blocking read with timeout function so we have to roll our own.
*/
int receive_from(
boost::asio::ip::udp::socket& socket,
const boost::asio::mutable_buffers_1& buf,
boost::asio::ip::udp::endpoint& remoteEndpoint,
boost::system::error_code& error,
chrono::milliseconds timeout)
{
volatile bool ioDone = false;
int numBytesReceived = 0;
boost::asio::io_service& ioService = socket.get_io_service();
socket.async_receive_from(buf, remoteEndpoint,
[&error, &ioDone, &numBytesReceived](const boost::system::error_code& errorAsync, size_t bytesReceived)
{
ioDone = true;
error = errorAsync;
numBytesReceived = bytesReceived;
});
this_thread::sleep_for(chrono::milliseconds(100));
ioService.reset();
ioService.poll_one();
auto endTime = chrono::system_clock::now() + timeout;
while (!ioDone)
{
ioService.reset();
this_thread::sleep_for(chrono::milliseconds(100));
auto now = chrono::system_clock::now();
if (now > endTime)
{
socket.cancel();
error = error::timed_out;
return 0;
}
ioService.poll_one();
}
ioService.reset();
return numBytesReceived;
}
I checked similar questions on Stack Overflow and found some that said the receiving socket has to be bound to INADDR_ANY in order to receive broadcast packets. I was originally creating the socket like this udp::socket socket(ioService, udp::endpoint(udp::v4(), portNum)); but have now changed it to use ip::address_v4::any() instead. That didn't make any difference.
Can anybody tell me what I need to change in order to receive the UDP broadcast packet as expected ?
I am running this on iMX6 devices running Linux and am compiling using boost 1.58.
I finally discovered why my code was never seeing the broadcast packets even though tcpdump proved that they were being received. After finding this StackOverflow question:
Disable reverse path filtering from Linux kernel space
it seems that I just needed to disable Reverse Path Filtering on both hosts like this:
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter
and then my code worked perfectly with no modifications. Hopefully this will help other people wondering why they can't get UDP broadcasts to the network broadcast address (255.255.255.255) to work.

Mac/iOS cannot receive UDP broadcast packet, but can send UDP broadcast packet

I am working on a cross-platform game using C/C++ and socket. I am using UDP broadcast (e.g. send to xx.xx.xx.255 if on a C-type LAN address) for discovering of nearby players in LAN game playing.
The issue is the Mac/iOS version can not receive broadcast UDP packet that sent by others (neither from Mac/iOS , nor from windows), while windows version is able the receive broadcast packet from Mac/iOS. Thus Mac/iOS can not discover any nearby players while windows can discover all nearby players. On the same socket handle, sending/receiving normal UDP packet works on all platforms (sent to a specific address instead of the broadcast address).
Every testing device has only one NIC, which is connected to a single WIFI router. Addresses are dynamically allocated by DHCP on the WIFI router. The socket is bind to exact local address instead of 0.0.0.0, and I am using port 19190. [ Thanks for reading my question :) ]
Following is the code for initializing the socket on all platforms. I do set the SO_BROADCAST flag on Mac/iOS otherwise UDP broadcast packet won't be sent successfully.
BOOL Socket::__Create(const struct sockaddr &BindTo, int addr_len, int nSocketType, BOOL reuse_addr, int AF)
{
ASSERT(m_hSocket == INVALID_SOCKET);
m_hSocket = socket(AF, nSocketType, 0);
if(INVALID_SOCKET != m_hSocket)
{
int on = 1;
if(SOCK_STREAM == nSocketType)
{ linger l = {1,0};
VERIFY(0==::setsockopt(m_hSocket,SOL_SOCKET,SO_LINGER,(char*)&l,sizeof(linger)));
#if defined(PLATFORM_MAC) || defined(PLATFORM_IOS)
VERIFY(0==::setsockopt(m_hSocket,SOL_SOCKET,SO_NOSIGPIPE,(void *)&on, sizeof(on)));
#endif
}
#if defined(PLATFORM_MAC) || defined(PLATFORM_IOS)
else if(SOCK_DGRAM == nSocketType)
{
VERIFY(0==::setsockopt(m_hSocket,SOL_SOCKET,SO_BROADCAST,(void *)&on, sizeof(on)));
}
#endif
if(reuse_addr)
{ VERIFY(0==setsockopt(m_hSocket,SOL_SOCKET,SO_REUSEADDR,(char*)&on,sizeof(on)));
}
if(0==bind(m_hSocket,&BindTo,addr_len))
{
return TRUE;
}
}
_LOG_WARNING("Socket Error = "<<GetLastError());
Close();
return FALSE;
}
Here is the receiving code:
BOOL Socket::__RecvFrom(LPVOID pData, UINT len, UINT& len_out, struct sockaddr &target, int addr_len, BOOL Peek)
{
SOCKET_SIZE_T la = addr_len;
int l = (int)recvfrom(m_hSocket,(char*)pData,len,Peek?MSG_PEEK:0,&target,&la);
if(l==SOCKET_ERROR)return FALSE;
len_out = l;
return la == addr_len;
}
Did you try to bind the socket to the broadcast address (the one you are sending to) ? – ElderBug
Also, it's not working when you bind to 0.0.0.0 ? – ElderBug

WSARecvFrom on unconnected UDP socket does not return

I am writing a small program that tests an UDP network service. The implementation of the service is allowed to create a new socket for the session and respond to the client from there, at which point the client is then required to talk to this address (similar to TFTP).
Minimal client sans error checking looks like this:
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
sockaddr_in destaddr = { ... };
MSGBUF msg[] = { ... };
DWORD sent;
WSASendTo(fd, msg, sizeof msg / sizeof *msg, &sent, 0, (sockaddr *)sa, sizeof sa, 0, 0);
char buffer[4096];
MSGBUF rcvmsg = { sizeof buffer, buffer };
DWORD received;
sockaddr_storage sa;
socklen_t sa_len = sizeof sa;
DWORD flags = 0;
WSARecvFrom(fd, &rcvmsg, 1, &received, &flags, (sockaddr *)&sa, &sa_len, 0, 0);
The client works fine if the server responds from the same address and port that the initial message was sent to, however replies from another port are silently discarded and the client hangs in WSARecvFrom.
Explicitly binding the socket to { AF_INET, INADDR_ANY, 0 } to force assignment of a local port, or invoking listen(fd, 5); makes no difference, as expected.
Is there anything in WSASendTo that implicitly connects an UDP socket, and if so, what should I do to avoid this?
UDP doesn't have connections. Datagrams are sent to and from ports; it's one-way communication.
It sounds to me like your server is letting itself be assigned a temporary port (i.e. passing 0 as the port in sockaddr_in), instead of using a specific port. This won't work.
Since UDP has no concept of a connection, each time you send data, it could be sent from a different port; the first send doesn't reserve the port that it was given, it just sends a datagram from it and then lets it go.
Your server should be binding itself to a specific port.
Meh, it was a firewall issue. Adding the application to the list of programs allowed to receive incoming traffic fixed the issue.

Same socket getting created

I have this piece of code where a server socket is created and is set to listen on a particular port number say 5005. Now once the accept socket function returns the socket that gets created is copied into the m_Socket variable and finally i shutdown the server socket named SocServer which was created locally.
Now my question
Is it possible that the SocServer(created initially) and m_Socket(copied when accept returns) get the same number say 1500.
struct sockaddr_in ServerSock; // Socket address structure to bind the Port Number to listen to
char *localIP ;
SOCKET SocServer;
//To Set up the sockaddr structure
ServerSock.sin_family = AF_INET;
ServerSock.sin_addr.s_addr = INADDR_ANY
ServerSock.sin_port = htons(PortNumber);//port number of 5005
// To Create a socket for listening on PortNumber
if(( SocServer = socket( AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET )
{
return FALSE;
}
//To bind the socket with wPortNumber
if(bind(SocServer,(sockaddr*)&ServerSock,sizeof(ServerSock))!=0)
{
return FALSE;
}
// To Listen for the connection on wPortNumber
if(listen(SocServer,SOMAXCONN)!=0)
{
return FALSE;
}
// Structure to get the IP Address of the connecting Entity
sockaddr_in insock;
int insocklen=sizeof(insock);
//To accept the Incoming connection on the wPortNumber
m_Socket=accept(SocServer,(struct sockaddr*)&insock,&insocklen);
//delete the server socket
if(SocServer != INVALID_SOCKET)
{
//To close and shutdown the Socserver
shutdown(SocServer, 2 );
closesocket(SocServer);
}
is it possible that Socserver and m_socket are the same because
as per my code the socket connection is established and for some other reason it gets closed and in TCPView it shows established for a while and then no connection at all.
Note: This happens only in some machines and is not reproducible always. Can any other network related issue be the cause.
Are you certain that the client who is connecting to your server did not close the connection? Also, you did not provide any function which uses the m_Socket so i cannot tell you if there is any problem while handling the incoming connection. I do not think that m_socket and SocServer may end up the same.
In this code:
m_Socket=accept(SocServer,(struct sockaddr*)&insock,&insocklen);
if(SocServer != INVALID_SOCKET)
why do you call accept() with what may apparently be a bad socket? And do you test the value you get back from accept() anywhere?