Master The Pico WiFi: UDP For Speed |
Written by Harry Fairhead & Mike James | |||||||||||||
Monday, 27 November 2023 | |||||||||||||
Page 1 of 2 What is the simplest of the TCP protocols? Answer UDP - it's error- prone, but fast. This is an extract from our latest book on the Pico in C. Master the Raspberry Pi Pico in C:
|
bytes |
|
0, 1 |
Source port number |
2, 3 |
Destination port number |
4, 5 |
Length of data payload including header |
6, 7 |
Checksum |
The source port number and checksum are optional and often set to zero and ignored. The length gives the total length of the payload including the header and hence has to be 8 or larger. The largest packet that can be sent is set by the use of a 16-bit value but it is actually smaller than you might expect due to the need to accommodate the IP header.
For IPv4 the largest UDP packet is 65,507 bytes. The checksum field holds a checksum for all of the data, the header and the IP header and it is used for optional error checking.
There are a range of standard port numbers that are used for particular tasks as is the case for TCP. For example, port 123 is used for SNTP and should be avoided for other purposes. Ports above 49152 are not standardized and can be used for anything. Of course, you still have to avoid collisions between different applications. One approach is to use a random assignment of port numbers with the server informing the client of the port in use by some other standard protocol.
UDP Server
A UDP server sends datagrams to another machine specified by IP address and port number. The other machine has to be ready to receive UDP packets, if not the packets are just lost as there is no checking that they have been correctly delivered. In this sense a UDP server isn’t really a server as it doesn’t allow a client to connect in any sense and it is simply a source of packets.
The basic operation of raw UDP is the same as for TCP. There is a PCB, Protocol Control Bock, that you have to initialize and there are functions to set the PCB up and to send and receive datagrams.
To create a UDP PCB we use:
struct udp_pcb *pcb = udp_new();
This has to be bound to an IP address and a port and these are used to determine which network interface is used to send the datagram. You can use IP_ADDR_ANY to use any available interface:
udp_bind(pcb, IP_ADDR_ANY, 8080);
The port used, 8080, isn’t typically used for UDP, but it has a higher probability of working through firewalls. If this program doesn’t work on a particular machine then it is almost certain that it is a firewall rule that is blocking it or the lack of a rule to allow it. If you specify a 0 for port it will automatically bind to a random port between UDP_LOCAL_PORT_RANGE_START and UDP_LOCAL_PORT_RANGE_END.
There are a number of ways of specifying the destination address, but storing it in the PCB follows the method that TCP uses:
ip_addr_t ip; IP4_ADDR(&ip, 192, 168, 11, 101); udp_connect(pcb,&ip,8080);
This doesn’t cause anything to happen on the network. It simply stores the information in the PCB. Notice that the remote port doesn’t have to be the same as the source port. If the remote machine needs to send datagrams back then, by default, it will either use the source port if specified or the remote port otherwise. There is a disconnect function:
udp_disconnect(pcb)
but all this does is to zero the fields in the PCB – there is no sense in which a UDP client and server are connected they simply exchange datagrams.