Im sending UDP packets using Indy's IdUDPClient component:
FIdUDPclient.sendbuffer( AIP, APort, FIdUDPBuffer );
Frecl := FIdUDPclient.receivebuffer( FIdRecBuff, FreceiveTimeout );
Right after i receive the answer.
Using wireshark while debugging the code showed that sometimes receivebuffer FIdRecBuff contains unexpected data.
For example, the received bytes reading with Wireshark:
45 02 57 00
But while debugging FIdRecBuff:
45 02 57 02
The above code is running in a worker thread with one dedicated IdUDPClient instance. I send only the same 3 bytes and getting 4 bytes as answer from each of the three IP device.
I thought the problem is that im sending UDP packets for three different IP device with no delay so the answering from the IPs are not in order. But indy's sendbuffer() method is blocking until receive so i dont understand.
Can someone explain what scenarios/conditions can lead to this behavior?
When sending packets to different hosts using TIdUDPClient in a serial manner -with the communication method im using-, the received packets from different hosts can 'interfere' with each other. UDP is a connectionless protocol so there is no any mechanism that can guarantee the right order of the receiving packets (not synchronous to sent packets) or the answering remote hosts.
For separating the received packets by remote hosts, the possible solutions are (thanks to Remy Lebeau):
Checking the received packets for the remote IP thats correspond to the sent packet.
Connect IdUDPClient to the remote IP. (IdUDPClient.binding then IdUDPClient.Connect)
Using IdUDPServer for sending packets, reading the answers in event handler OnUDPRead.
(Yet the right order of the received packets from the same remote host is not guaranteed, but right now that is not my goal).
Related
I have created a test account to IOThub and pulled down the azure-iot-sdks git archive to test with.
I have added my connection string to both the iothub_client_sample_http and iothub_client_sample_mqtt .c files.
When I run the iothub_client_sample_http I see a couple of network packets sent and acked before I get a segmentation violation in pthread_mutex_lock called from PR_lock. I will track this down and fix it.
More importantly, I want to use the MQTT protocol. When I execute the iothub_client_sample_mqtt app I get a timeout in the connect code. I have looked at the packets with wire shark and what I see is:
TCP 74 33226 > secure-mqtt [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=81898578 TSecr=0 WS=128
Then two more packets going out the same with retransmission. I never see any reply packets.
Is there something I need to enable at the IOThub to allow using MQTT?
I actually want to use mosquitto in the product and I get the same scenario from my code.
Thanks for any help.
You can also use MQTT over WebSockets which uses 443 port instead of 8883.
See more details from https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-mqtt-support
Thanks for the answer. It turns out the company was filtering all packets to port 8883 and that was my issue.
MQTT has some particular advantages over other protocols to the hub. As it becomes more popular IT organizations will need to change this type of thing.
Thanks again.
I'm trying to implement the following UDP protocol, but I'm having a little trouble figuring exactly how I should approach this.
The protocol states that I should send a particular UDP packet to a certain server, after which the server will stream (several UDP packets that are related) a response back to me, also as UDP packets. I have managed to send the UDP packet fine using the following code:
connection, error := net.DialUDP("udp", nil, endpoint)
...
if written, error := connection.Write(query.ToBytes()); error != nil {
...
} else {
log.Printf("Successfully wrote %d bytes to %s", written, connection.RemoteAddr())
}
When I use Wireshark and take a look at what's going over the wire, it looks like it sent the packet just fine (the only issue here is that I never get a reply from the server, but that's unrelated to this question).
What's the best way for me to handle the server reply in this case? Can I use the previously established connection to read server responses back (this seems unlikely to me, as it's UDP so connectionless) or should I use net.ListenUDP(...) to establish a server on the correct local address and port to read whatever the server sends back to me?
The intent of the protocol is clearly that you just use the same UDP socket to receive the reply that you used to send the request. If you have a client-side firewall, you will have to explicitly open a UDP port and bind the UDP socket to that port before you send. Otherwise just let the system choose the local port, by not binding at all.
The phrase 'the same port as was established by the intial packet' is misleading. Are they your words, or the protocol specification's? What really happens when you do the first send is that if you haven't bound the socket yet, it is automatically bound to a system-chosen port, exactly as if you had bound it to port zero.
Because of the specific protocol design, it's impossible to know on which port the server will send its reply packets. After taking a second look at the packet dumps, I noticed that the server in fact does reply, only the client immediately replies back with an ICMP message saying Destination port unreachable. So the server was trying to reply, but it couldn't because the client would not accept the packets on that port.
To solve this, I have used net.ListenUDP to listen for incoming packets immediately after the client sends the initial packet using the established connection's local address:
incomingConnection, _ := net.ListenUDP("udp", connection.LocalAddr().(*net.UDPAddr))
log.Printf("Listening for packets on %s", incomingConnection.LocalAddr())
defer incomingConnection.Close()
After which incomingConnection can be used as a Reader - for example - read the packets that the server is sending.
I have a server running on a Windows 7 desktop PC, and a client running on a Windows XP Lenovo laptop.
The following keeps happening in a loop:
The client is broadcasting UDP packets containing some ID info.
The server gets the broadcast and replies with another UDP packet with some data inside.
I can see in Wireshark that the server is sending the proper data, but the RECVFROM function is returning some other data. After around 20-30 seconds the data is finally read correctly.
If I run both the server and client on the desktop it works fine. Any ideas?
Relevant piece of code:
do
{
result=recvfrom(_socket,buff,buffLen,0,(SOCKADDR*)&SenderAddr,&SenderAddrSize);
if(result != SOCKET_ERROR)
{
//small processing
.....
////
sendto(_socket,buff,16,0,(SOCKADDR*)&SenderAddr,sizeof(SenderAddr));
}
while(true)
Taking a bit of a guess here.
I can't imagine that your UDP packets wonder around somewhere for 20 seconds. After all RTT around the globe over the public Internet is usually 40 times less then that. So I think you just keep re-sending your data until you get the expected response.
If I am right with my assumption then what you see is a normal UDP packet loss. Is that laptop on a wireless link? Does the client app block on some input?
Run wireshark on the laptop too. Do you see the same number and sequence of packets as on the sender (server) side? If so, then the client does not consume those packets fast enough. If you actually see the packets back on the client with that 20 second delay then you really have to describe more of your setup to explain the magic :)
Thanks for your answers..
The problem was that the sendto method was behaving differently on laptop comparing to the desktop.
On laptot sendto was sending 3 UDP packets, on the destop only one.
My application was expecting only one packet,so the processing time + multiply by 3 gives the impression of delay.
I don't understand why this happens but this was the problem.
I want to send broadcast message to all peers in my local network. Message is a 32 bit integer. I can be sure, that message will not me fragmented, right? There will be two options:
- peer will receive whole message at once
- peer will not receive message at all
Going further, 4 bytes is maximum size of data, that can be sent in one UDP datagram? I use Ethernet based network in 99%.
IPv4 specifies a minimum supported MTU of 576 bytes, including the IP header. Your 4 byte UDP payload will result in an IP packet far smaller than this, so you need not fear fragmentation.
Furthermore, your desired outcome - "peer will receive whole message at once or peer will not receive message at all" is always how UDP works, even in the presence of fragmentation. If a fragment doesn't arrive, your app won't recieve the packet at all.
The rules for UDP are "The packet may arrive out-of-order, duplicated, or not at all. If the packet does arrive, it will be the whole packet and error-free.". ("Error-free" is obviously only true within the modest limits of the IP checksum).
Ethernet packets can be up to around 1500 bytes (and that's not counting jumbo frames). If you send broadcast messages with a payload of only 4 bytes, they shouldn't get fragmented at all. Fragmentation should only occur when the packet is larger than the Maximum Transmission Unit (so about 1500 bytes over Ethernet).
I have created a raw socket which takes all IPv4 packets from data link layer (with data link layer header removed). And for reading the packets I use recvfrom.
My doubt is:
Suppose due to some scheduling done by OS, my process was asleep for 1 sec. When it woke up,it did recvfrom (with number of bytes to be received say 1000) on this raw socket (with the intention of receiving only one IPv4 packet and say the size of this packet is 380 bytes). And suppose many network applications were also running simultaneously during this time, so all IPv4 packets must have been queued in the receive buffer of this socket. So now recvfrom will return all 1000 bytes (with other IPv4 packets from 381th byte onwards) bcoz it has enough data in its buffer to return. Although my program was meant to understand only one IPv4 packet
So how to prevent this thing? Should I read byte by byte and parse each byte but it is very inefficient.
IIRC, recvfrom() will only return one packet at a time, even if there are more in the queue.
Raw sockets operate at the packet layer, there is no concept of data streams.
You might be interested in recvmmsg() if you want to read multiple packets in one system call. Recent Linux kernels only, there is no equivalent send side implementation.