NetBurner 3.5.6
PDF Version
UDP Socket API

BSD-style socket functions for UDP communication. More...

Functions

int CreateRxUdpSocket (uint16_t listening_port)
 Create receive-only UDP socket bound to specified port.
 
int CreateTxUdpSocket (const IPADDR &send_to_addr, uint16_t remote_port, uint16_t local_port)
 Create transmit-only UDP socket for sending to specified destination.
 
int CreateRxTxUdpSocket (const IPADDR &send_to_addr, uint16_t send_to_remote_port, uint16_t local_port)
 Create bidirectional UDP socket for both sending and receiving.
 
int sendto (int sock, puint8_t what_to_send, int len_to_send, const IPADDR &to_addr, uint16_t remote_port)
 Send UDP packet through socket to specified destination.
 
int sendtovia (int sock, puint8_t what_to_send, int len_to_send, const IPADDR &to_addr, uint16_t remote_port, int intfnum)
 Send via specific interface.
 
int recvfrom (int sock, puint8_t buffer, int len, IPADDR *pAddr, uint16_t *pLocal_port, uint16_t *pRemote_port)
 Receive UDP packet from socket with sender information.
 
int SendFragmentedUdpPacket (const IPADDR &to, uint16_t source_port, uint16_t dest_port, puint8_t data, int length)
 Send large UDP packet (>MTU) with IP fragmentation.
 

Detailed Description

BSD-style socket functions for UDP communication.

Provides familiar Berkeley Sockets (BSD) style interface for UDP networking. These functions offer an alternative to the UDPPacket class for developers who prefer traditional socket programming or are porting existing code.

Overview

The UDP Socket API provides three main operation types:

Key Concepts

Socket Types

1. Receive-Only Socket (Server/Listener)

2. Transmit-Only Socket (Client/Sender)

3. Bidirectional Socket (Request/Response)

Port Number Selection

Local Port (Binding)

Remote Port (Destination)

// Server pattern - fixed local port
int serverSock = CreateRxUdpSocket(8080);
// Client pattern - auto-assign local port
int clientSock = CreateTxUdpSocket(serverIP, 8080, 0);
int CreateTxUdpSocket(const IPADDR &send_to_addr, uint16_t remote_port, uint16_t local_port)
Create transmit-only UDP socket for sending to specified destination.
Definition udp.h:5563
int CreateRxUdpSocket(uint16_t listening_port)
Create receive-only UDP socket bound to specified port.

Common Usage Patterns

Examples

Pattern 1: Simple UDP Server
#include <udp.h>
#include <init.h>
void UdpServerTask(void* pd) {
int sock = CreateRxUdpSocket(5000);
if (sock < 0) {
printf("Failed to create socket: %d\r\n", sock);
return;
}
uint8_t buffer[1024];
IPADDR clientIP;
uint16_t localPort, remotePort;
while (1) {
int n = recvfrom(sock, buffer, sizeof(buffer),
&clientIP, &localPort, &remotePort);
if (n > 0) {
printf("Received %d bytes from %s:%d\r\n",
n, AsciiIP(clientIP).c_str(), remotePort);
// Echo back to sender
sendto(sock, buffer, n, clientIP, remotePort);
}
}
}
Used to hold and manipulate IPv4 and IPv6 addresses in dual stack mode.
Definition ipv6_addr.h:41
int recvfrom(int sock, puint8_t buffer, int len, IPADDR *pAddr, uint16_t *pLocal_port, uint16_t *pRemote_port)
Receive UDP packet from socket with sender information.
Definition udp.h:5960
int sendto(int sock, puint8_t what_to_send, int len_to_send, const IPADDR &to_addr, uint16_t remote_port)
Send UDP packet through socket to specified destination.
Definition udp.h:5876
Pattern 2: UDP Client (One-Way Sender)
void SendSensorData(IPADDR serverIP, int sensorValue) {
// Create socket with auto-assigned local port (0)
int sock = CreateTxUdpSocket(serverIP, 5000, 0);
if (sock < 0) {
printf("Socket creation failed\r\n");
return;
}
char msg[64];
int len = sprintf(msg, "SENSOR:%d,VALUE:%d",
GetDeviceID(), sensorValue);
sendto(sock, (uint8_t*)msg, len, serverIP, 5000);
close(sock);
}
int close(int fd)
Close the specified file descriptor and free the associated resources.
Pattern 3: Request/Response (Bidirectional)
int QueryServer(IPADDR serverIP, const char* request,
char* response, int maxLen) {
// Create bidirectional socket
int sock = CreateRxTxUdpSocket(serverIP, 6000, 0);
if (sock < 0) return -1;
// Send request
sendto(sock, (uint8_t*)request, strlen(request), serverIP, 6000);
// Wait for response with timeout
fd_set readfds;
struct timeval tv = {5, 0}; // 5 second timeout
FD_ZERO(&readfds);
FD_SET(sock, &readfds);
if (select(sock + 1, &readfds, NULL, NULL, &tv) > 0) {
IPADDR srcIP;
uint16_t localPort, remotePort;
int n = recvfrom(sock, (uint8_t*)response, maxLen,
&srcIP, &localPort, &remotePort);
close(sock);
return n;
}
close(sock);
return 0; // Timeout
}
void FD_SET(int fd, fd_set *pfds)
A fd_set (file descriptor set) holds a set of file descriptors (fds). This function sets or adds a sp...
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, unsigned long timeout)
Wait for events to occur on one or more I/O resources associated with a set of file descriptors (fds)...
void FD_ZERO(fd_set *pfds)
Clear (set to 0) a fd_set (file descriptor set) so no file descriptors (fds) are selected.
int CreateRxTxUdpSocket(const IPADDR &send_to_addr, uint16_t send_to_remote_port, uint16_t local_port)
Create bidirectional UDP socket for both sending and receiving.
Definition udp.h:5748
Pattern 4: Multi-Interface Routing
// Send via specific network interface (multi-homed device)
void SendViaInterface(IPADDR destIP, int interfaceNum) {
int sock = CreateTxUdpSocketVia(destIP, 8080, 0, interfaceNum);
if (sock >= 0) {
uint8_t data[] = "Hello from specific interface";
sendtovia(sock, data, sizeof(data), destIP, 8080, interfaceNum);
close(sock);
}
}
int sendtovia(int sock, puint8_t what_to_send, int len_to_send, const IPADDR &to_addr, uint16_t remote_port, int intfnum)
Send via specific interface.
Definition udp.h:5899
Pattern 5: Broadcast Discovery
void DiscoverDevices() {
IPADDR broadcastAddr = AsciiToIp("255.255.255.255");
int sock = CreateTxUdpSocket(broadcastAddr, 9999, 0);
if (sock >= 0) {
uint8_t discover[] = "DISCOVER:NetBurner";
sendto(sock, discover, sizeof(discover), broadcastAddr, 9999);
// Listen for responses
uint8_t buf[256];
IPADDR responderIP;
uint16_t lp, rp;
while (recvfrom(sock, buf, sizeof(buf), &responderIP, &lp, &rp) > 0) {
printf("Found device at %s\r\n", AsciiIP(responderIP).c_str());
}
close(sock);
}
}
Pattern 6: Using select() for Multiple Sockets
void MultiSocketHandler() {
int sock1 = CreateRxUdpSocket(5000);
int sock2 = CreateRxUdpSocket(5001);
int maxfd = (sock1 > sock2) ? sock1 : sock2;
fd_set readfds;
uint8_t buffer[512];
IPADDR srcIP;
uint16_t lp, rp;
while (1) {
FD_ZERO(&readfds);
FD_SET(sock1, &readfds);
FD_SET(sock2, &readfds);
if (select(maxfd + 1, &readfds, NULL, NULL, NULL) > 0) {
if (FD_ISSET(sock1, &readfds)) {
int n = recvfrom(sock1, buffer, sizeof(buffer),
&srcIP, &lp, &rp);
printf("Port 5000: %d bytes\r\n", n);
}
if (FD_ISSET(sock2, &readfds)) {
int n = recvfrom(sock2, buffer, sizeof(buffer),
&srcIP, &lp, &rp);
printf("Port 5001: %d bytes\r\n", n);
}
}
}
}
int FD_ISSET(int fd, fd_set *pfds)
A fd_set (file descriptor set) holds a set of file descriptors (fds). This function checks whether or...

Error Handling

All socket creation functions return:

Common error codes:

int sock = CreateRxUdpSocket(port);
if (sock < 0) {
switch (sock) {
printf("Socket does not exist\r\n");
break;
printf("Cannot write to socket\r\n");
break;
printf("Cannot read from socket\r\n");
break;
default:
printf("Unknown error: %d\r\n", sock);
}
return;
}
#define UDP_ERR_NOTOPEN_TO_READ
Socket not open for read.
Definition udp.h:4764
#define UDP_ERR_NOSUCH_SOCKET
Socket does not exist.
Definition udp.h:4762
#define UDP_ERR_NOTOPEN_TO_WRITE
Socket not open for write.
Definition udp.h:4763

Thread Safety

// Good: Each task uses its own socket
void Task1(void* pd) {
int sock = CreateRxUdpSocket(5000);
// ... use sock ...
}
void Task2(void* pd) {
int sock = CreateRxUdpSocket(5001);
// ... use sock ...
}

Performance Considerations

Buffer Sizing

Optimization Tips

  1. Reuse sockets: Create once, use many times
  2. Batch operations: Send multiple packets before context switch
  3. Appropriate buffer sizes: Match expected packet sizes
  4. Interface binding: Reduce routing overhead in multi-homed systems
  5. Port reuse: Close sockets when no longer needed

IPv4 vs IPv6

The API automatically handles both IPv4 and IPv6 based on IPADDR type:

#ifdef IPV6
// Dual-stack - works with both IPv4 and IPv6
IPADDR destIP = AsciiToIp("2001:db8::1"); // IPv6
// or
IPADDR destIP = AsciiToIp("192.168.1.100"); // IPv4-mapped
int sock = CreateTxUdpSocket(destIP, 8080, 0);
#else
// IPv4 only
IPADDR4 destIP = AsciiToIp4("192.168.1.100");
int sock = CreateTxUdpSocket(destIP, 8080, 0);
#endif
Used to store and manipulate IPv4 addresses in dual stack mode.
Definition nettypes.h:225
IPADDR4 AsciiToIp4(const char *p)
Convert an ASCII IPv4 string to an IP address.

Multi-Homed Systems

For devices with multiple network interfaces:

Interface Number (Preferred)

// Send via interface 1 (second Ethernet, Wi-Fi, etc.)
int sock = CreateTxUdpSocketVia(destIP, 8080, 0, 1);
sendtovia(sock, data, len, destIP, 8080, 1);

Interface IP Address (Alternative)

// Send via specific interface IP
IPADDR myInterfaceIP = GetInterfaceIP(1);
int sock = CreateTxUdpSocketVia(destIP, 8080, 0, myInterfaceIP);

Comparison with UDPPacket Class

Feature BSD Sockets UDPPacket Class
API Style Familiar C functions C++ object-oriented
Memory Management Manual Automatic (RAII)
Buffer Access Copy-based Zero-copy available
Multi-destination Multiple sends SendAndKeep() support
Integration select()/poll() OS_FIFO queues
Portability Standard POSIX NetBurner-specific
Best For Porting code, C code New C++ projects

When to Use BSD Sockets:

When to Use UDPPacket:

Advanced Features

Large Packet Transmission (Fragmentation)

For packets exceeding MTU, use SendFragmentedUdpPacket():

uint8_t largeData[5000];
// ... fill largeData ...
destIP,
0, // source port (0 = auto-assign)
8080, // destination port
largeData,
sizeof(largeData)
);
if (result == sizeof(largeData)) {
printf("Successfully sent %d bytes\r\n", result);
} else {
printf("Send failed or partial: %d/%d bytes\r\n",
result, sizeof(largeData));
}
int SendFragmentedUdpPacket(const IPADDR &to, uint16_t source_port, uint16_t dest_port, puint8_t data, int length)
Send large UDP packet (>MTU) with IP fragmentation.
Definition udp.h:6018

Note: Fragmentation should be avoided when possible due to:

Socket Lifecycle Management

// Create socket
int sock = CreateRxTxUdpSocket(serverIP, 8080, 0);
if (sock < 0) {
// Handle error
return;
}
// Use socket for communication
// ...
// Close socket when done
close(sock);
// Socket descriptor is now invalid

Common Pitfalls

[NO] Not checking return values

int sock = CreateRxUdpSocket(5000);
recvfrom(sock, buf, len, &ip, &lp, &rp); // BUG: sock might be negative!

[YES] Always validate

int sock = CreateRxUdpSocket(5000);
if (sock < 0) {
printf("Socket creation failed: %d\r\n", sock);
return;
}
recvfrom(sock, buf, len, &ip, &lp, &rp);

[NO] Buffer overflow

uint8_t buf[100];
recvfrom(sock, buf, 1000, &ip, &lp, &rp); // BUG: Buffer too small!

[YES] Match buffer size

uint8_t buf[1500];
int n = recvfrom(sock, buf, sizeof(buf), &ip, &lp, &rp);
if (n > 0 && n < sizeof(buf)) {
// Process n bytes safely
}

[NO] Ignoring recvfrom() return value

uint8_t buf[512];
recvfrom(sock, buf, sizeof(buf), &ip, &lp, &rp);
printf("%s", buf); // BUG: Might print garbage or crash!

[YES] Check bytes received

uint8_t buf[512];
int n = recvfrom(sock, buf, sizeof(buf), &ip, &lp, &rp);
if (n > 0) {
buf[n] = '\0'; // Safe null-termination
printf("%s", buf);
}

[NO] Port conflicts

int sock1 = CreateRxUdpSocket(8080);
int sock2 = CreateRxUdpSocket(8080); // BUG: Port already in use!

[YES] Unique ports or reuse pattern

int sock1 = CreateRxUdpSocket(8080);
// ... use sock1 ...
close(sock1);
// Now safe to reuse port
int sock2 = CreateRxUdpSocket(8080);

Debugging Tips

  1. Enable diagnostics: Call EnableSystemDiagnostics() in UserMain()
  2. Check socket descriptor: Valid sockets are >= 0
  3. Verify network connectivity: Ensure interface is up and configured
  4. Monitor packet capture: Use Wireshark to inspect actual traffic
  5. Test with known tools: Use netcat (nc) for quick testing: ```bash

Send UDP packet from command line

echo "test" | nc -u 192.168.1.100 8080

Listen for UDP packets

nc -ul 8080 ```

  1. Check firewall rules: Ensure UDP traffic is not blocked
  2. Validate addresses: Use AsciiIP() to print addresses for debugging

Related Topics

Function Documentation

◆ CreateRxTxUdpSocket()

int CreateRxTxUdpSocket ( const IPADDR & send_to_addr,
uint16_t send_to_remote_port,
uint16_t local_port )
inline

#include <udp.h>

Create bidirectional UDP socket for both sending and receiving.

Creates a UDP socket that can both send packets to a specified destination and receive packets on a local port. This combines the functionality of CreateTxUdpSocket() and CreateRxUdpSocket() into a single socket, ideal for request/response patterns and client-server communication.

Socket Characteristics:

  • Can send to pre-configured destination
  • Can receive on bound local port
  • Single socket for bidirectional communication
  • Efficient for request/response protocols

Common Use Cases:

  • Client applications expecting replies (DNS queries, SNMP, RPC)
  • Request/response protocols
  • Duplex communication patterns
  • Protocols requiring both send and receive on same endpoint
Parameters
send_to_addrDestination IP address for sending packets Use AsciiToIp() or AsciiToIp4() to convert from string
send_to_remote_portDestination port number for sending (1-65535)
local_portLocal port to bind for receiving (0-65535)
  • 0: Auto-assign ephemeral port (common for clients)
  • 1-65535: Specific port (required if server must reply to known port)
Returns
Socket file descriptor (>= 0) on success, negative error code on failure:
  • UDP_ERR_NOSUCH_SOCKET (-1): Socket creation failed
  • UDP_ERR_NOTOPEN_TO_WRITE (-2): Socket not writable
  • UDP_ERR_NOTOPEN_TO_READ (-3): Socket not readable
Note
Port Selection: Use 0 for local_port if server response port doesn't matter. Use specific port only when protocol requires clients to listen on fixed ports.
Response Handling: Responses will arrive on the local_port. Use recvfrom() to receive them. The remote source may be different from send_to_addr.
Warning
Thread Safety: Socket should be used by single task. Do not call sendto() and recvfrom() concurrently from multiple tasks on same socket.

Expand for Example Usage

Examples

Example 1: DNS Query (Request/Response Pattern)

#include <udp.h>
bool DnsQuery(const char* hostname, IPADDR* result) {
IPADDR dnsServer = AsciiToIp("8.8.8.8");
// Create bidirectional socket for DNS query and response
int sock = CreateRxTxUdpSocket(dnsServer, 53, 0);
if (sock < 0) return false;
// Build DNS query packet
uint8_t query[512];
int queryLen = BuildDnsQuery(query, hostname);
// Send query
sendto(sock, query, queryLen, dnsServer, 53);
// Wait for response with timeout
fd_set readfds;
struct timeval tv = {5, 0}; // 5 second timeout
FD_ZERO(&readfds);
FD_SET(sock, &readfds);
if (select(sock + 1, &readfds, NULL, NULL, &tv) > 0) {
uint8_t response[512];
IPADDR srcIP;
uint16_t lp, rp;
int n = recvfrom(sock, response, sizeof(response),
&srcIP, &lp, &rp);
if (n > 0) {
*result = ParseDnsResponse(response, n);
close(sock);
return true;
}
}
close(sock);
return false; // Timeout or error
}

Example 2: Echo Client with Response

void EchoClientTest() {
IPADDR serverIP = AsciiToIp("192.168.1.100");
// Create bidirectional socket
int sock = CreateRxTxUdpSocket(serverIP, 5000, 0);
if (sock < 0) {
printf("Socket creation failed\r\n");
return;
}
// Send message
const char* msg = "Hello, Server!";
sendto(sock, (uint8_t*)msg, strlen(msg), serverIP, 5000);
printf("Sent: %s\r\n", msg);
// Wait for echo response
uint8_t buf[256];
IPADDR respIP;
uint16_t lp, rp;
int n = recvfrom(sock, buf, sizeof(buf), &respIP, &lp, &rp);
if (n > 0) {
buf[n] = '\0';
printf("Received echo: %s\r\n", buf);
}
close(sock);
}

Example 3: Persistent Connection Pattern

void RequestResponseLoop() {
IPADDR serverIP = AsciiToIp("10.0.0.50");
// Create persistent bidirectional socket
int sock = CreateRxTxUdpSocket(serverIP, 6000, 0);
if (sock < 0) return;
uint8_t request[64];
uint8_t response[256];
IPADDR respIP;
uint16_t lp, rp;
for (int i = 0; i < 10; i++) {
// Send request
int reqLen = sprintf((char*)request, "REQ:%d", i);
sendto(sock, request, reqLen, serverIP, 6000);
// Wait for response
int n = recvfrom(sock, response, sizeof(response),
&respIP, &lp, &rp);
if (n > 0) {
response[n] = '\0';
printf("Response %d: %s\r\n", i, response);
}
OSTimeDly(TICKS_PER_SECOND);
}
close(sock);
}
#define TICKS_PER_SECOND
System clock ticks per second.
Definition constants.h:49


See also
CreateTxUdpSocket() - For send-only sockets (one-way communication)
CreateRxUdpSocket() - For receive-only sockets (servers)
CreateRxTxUdpSocketVia() - For multi-interface routing
sendto() - Send data through socket
recvfrom() - Receive data from socket
select() - Wait for socket to be ready with timeout
close() - Close socket when finished

◆ CreateRxUdpSocket()

int CreateRxUdpSocket ( uint16_t listening_port)

#include <udp.h>

Create receive-only UDP socket bound to specified port.

Creates a UDP socket configured only for receiving packets. The socket is bound to the specified local port and can receive UDP packets from any source. This is the standard function for creating UDP server/listener sockets.

Socket Characteristics:

  • Bound to specified local port
  • Receives from any source IP/port
  • Cannot send packets (receive-only)
  • Suitable for servers and broadcast receivers

Common Use Cases:

  • UDP servers listening for client requests
  • Broadcast/multicast receivers
  • Service discovery listeners
  • Logging/monitoring receivers
Parameters
listening_portLocal port number to bind (1-65535)
  • Well-known ports (1-1023): Standard services (use with caution)
  • Registered ports (1024-49151): Custom applications (recommended)
  • Dynamic ports (49152-65535): Temporary/ephemeral use
Returns
Socket file descriptor (>= 0) on success, negative error code on failure:
  • UDP_ERR_NOSUCH_SOCKET (-1): Socket creation failed
  • UDP_ERR_NOTOPEN_TO_READ (-3): Internal error - socket not readable
Note
Port Availability: The port must not already be in use by another socket. Use UnregisterUDPFifo() or close() existing sockets before reusing ports.
Thread Safety: The returned socket should only be used by a single task. For multi-task reception, create separate sockets on different ports or use the UDPPacket class with OS_FIFO for thread-safe queue-based reception.
Warning
Error Checking Required: Always check return value before using socket. Attempting to use a negative file descriptor will cause undefined behavior.

Expand for Example Usage

Examples

Example 1: Simple UDP Server

#include <udp.h>
#include <init.h>
void UdpServerTask(void* pd) {
// Create receive-only socket on port 8080
int sock = CreateRxUdpSocket(8080);
if (sock < 0) {
printf("Failed to create socket: error %d\r\n", sock);
return;
}
printf("UDP server listening on port 8080\r\n");
uint8_t buffer[1024];
IPADDR clientIP;
uint16_t localPort, remotePort;
while (1) {
// Wait for incoming packet
int n = recvfrom(sock, buffer, sizeof(buffer),
&clientIP, &localPort, &remotePort);
if (n > 0) {
buffer[n] = '\0'; // Null-terminate for printing
printf("Received %d bytes from %s:%d: %s\r\n",
n, AsciiIP(clientIP).c_str(), remotePort, buffer);
}
}
// Clean up (typically never reached in server loop)
close(sock);
}

Example 2: Echo Server

void UdpEchoServer() {
int sock = CreateRxUdpSocket(5000);
if (sock < 0) return;
uint8_t buf[512];
IPADDR srcIP;
uint16_t lp, rp;
while (1) {
int n = recvfrom(sock, buf, sizeof(buf), &srcIP, &lp, &rp);
if (n > 0) {
// Note: Cannot echo back using this socket - it's receive-only!
// Need CreateRxTxUdpSocket() for bidirectional operation
printf("Echo server received: %d bytes\r\n", n);
}
}
}

Example 3: Broadcast Receiver

void BroadcastListener() {
int sock = CreateRxUdpSocket(9999);
if (sock < 0) {
printf("Cannot create broadcast listener\r\n");
return;
}
printf("Listening for broadcast packets on port 9999\r\n");
uint8_t buf[256];
IPADDR senderIP;
uint16_t lp, rp;
while (1) {
int n = recvfrom(sock, buf, sizeof(buf), &senderIP, &lp, &rp);
if (n > 0) {
buf[n] = '\0';
printf("Broadcast from %s: %s\r\n",
AsciiIP(senderIP).c_str(), buf);
}
}
}


See also
CreateRxTxUdpSocket() - For bidirectional sockets (receive and send)
CreateTxUdpSocket() - For transmit-only sockets
CreateRxUdpSocketVia() - For multi-interface systems
recvfrom() - Receive data from socket
RegisterUDPFifo() - Alternative using UDPPacket class with OS_FIFO
close() - Close socket when finished

◆ CreateTxUdpSocket()

int CreateTxUdpSocket ( const IPADDR & send_to_addr,
uint16_t remote_port,
uint16_t local_port )
inline

#include <udp.h>

Create transmit-only UDP socket for sending to specified destination.

Creates a UDP socket configured only for sending packets to a specific remote address and port. The socket can optionally be bound to a specific local port, or use 0 to auto-assign an ephemeral port (recommended for most clients).

Socket Characteristics:

  • Send-only (cannot receive packets)
  • Pre-configured with destination address and port
  • Optional local port binding (0=auto-assign)
  • Suitable for client applications and sensors

Common Use Cases:

  • UDP clients sending requests to servers
  • Sensor data transmission
  • Logging to remote syslog servers
  • Periodic status updates to monitoring systems
Parameters
send_to_addrDestination IP address (IPv4 or IPv6 depending on build config) Use AsciiToIp() or AsciiToIp4() to convert from string
remote_portDestination port number (1-65535) Must match the listening port on remote system
local_portLocal port to bind (0-65535)
  • 0: Auto-assign ephemeral port (RECOMMENDED for clients)
  • 1-65535: Specific port (use only if required by protocol)
Returns
Socket file descriptor (>= 0) on success, negative error code on failure:
  • UDP_ERR_NOSUCH_SOCKET (-1): Socket creation failed
  • UDP_ERR_NOTOPEN_TO_WRITE (-2): Internal error - socket not writable
Note
Local Port Recommendation: Use 0 for automatic port assignment unless your protocol specifically requires a fixed source port. Auto-assignment prevents port conflicts and is standard practice for UDP clients.
Destination Changes: This socket is bound to the specified destination. To send to different destinations, use sendto() or create multiple sockets.
Warning
Send-Only: This socket cannot receive packets. For bidirectional communication (request/response patterns), use CreateRxTxUdpSocket().

Expand for Example Usage

Examples

Example 1: Simple UDP Client

#include <udp.h>
void SendMessage(const char* message) {
IPADDR serverIP = AsciiToIp("192.168.1.100");
// Create socket with auto-assigned local port (0)
int sock = CreateTxUdpSocket(serverIP, 8080, 0);
if (sock < 0) {
printf("Failed to create socket\r\n");
return;
}
// Send message
int sent = sendto(sock, (uint8_t*)message, strlen(message),
serverIP, 8080);
if (sent > 0) {
printf("Sent %d bytes\r\n", sent);
}
close(sock);
}

Example 2: Periodic Sensor Data Transmission

void SensorTransmitTask(void* pd) {
IPADDR serverIP = AsciiToIp("10.0.1.50");
// Create persistent socket (reuse for efficiency)
int sock = CreateTxUdpSocket(serverIP, 5000, 0);
if (sock < 0) return;
char msgBuf[64];
while (1) {
// Read sensor
int temperature = ReadTemperatureSensor();
int humidity = ReadHumiditySensor();
// Format message
int len = sprintf(msgBuf, "TEMP:%d,HUM:%d",
temperature, humidity);
// Send to server
sendto(sock, (uint8_t*)msgBuf, len, serverIP, 5000);
// Wait before next transmission
OSTimeDly(TICKS_PER_SECOND * 10); // Every 10 seconds
}
}

Example 3: Syslog Client

void SendSyslogMessage(const char* msg, int severity) {
IPADDR syslogServer = AsciiToIp("192.168.1.10");
int sock = CreateTxUdpSocket(syslogServer, 514, 0); // Syslog port
if (sock >= 0) {
char syslogMsg[512];
int len = sprintf(syslogMsg, "<%d>%s", severity, msg);
sendto(sock, (uint8_t*)syslogMsg, len, syslogServer, 514);
close(sock);
}
}

Example 4: Multiple Destinations (Create Multiple Sockets)

void SendToMultipleServers() {
IPADDR server1 = AsciiToIp("192.168.1.10");
IPADDR server2 = AsciiToIp("192.168.1.20");
int sock1 = CreateTxUdpSocket(server1, 8080, 0);
int sock2 = CreateTxUdpSocket(server2, 8080, 0);
uint8_t data[] = "Status update";
if (sock1 >= 0) {
sendto(sock1, data, sizeof(data), server1, 8080);
close(sock1);
}
if (sock2 >= 0) {
sendto(sock2, data, sizeof(data), server2, 8080);
close(sock2);
}
}


See also
CreateRxTxUdpSocket() - For bidirectional communication (send and receive)
CreateRxUdpSocket() - For receive-only sockets (servers)
CreateTxUdpSocketVia() - For multi-interface routing
sendto() - Send data through socket
close() - Close socket when finished

◆ recvfrom()

int recvfrom ( int sock,
puint8_t buffer,
int len,
IPADDR * pAddr,
uint16_t * pLocal_port,
uint16_t * pRemote_port )
inline

#include <udp.h>

Receive UDP packet from socket with sender information.

Receives a UDP datagram from the specified socket and returns the sender's IP address and port. This is the standard BSD socket function for receiving UDP data. Works with sockets created by CreateRxUdpSocket() or CreateRxTxUdpSocket(). Blocks until data arrives.

Parameters
sockSocket file descriptor from CreateRxUdpSocket() or CreateRxTxUdpSocket()
bufferDestination buffer for received data
lenMaximum bytes to read (buffer size, recommend 1500+ bytes)
pAddr[OUT] Sender's IP address (can be NULL)
pLocal_port[OUT] Local port packet arrived on (can be NULL)
pRemote_port[OUT] Sender's port number (can be NULL)
Returns
Bytes received (0 to len), or negative error code:
  • UDP_ERR_NOTOPEN_TO_READ (-3): Socket not configured for receiving
  • UDP_ERR_NOSUCH_SOCKET (-1): Invalid socket
Note
Blocking: Waits indefinitely for data. Use select() for timeout.
Datagram Boundaries: Each call returns one complete datagram.
Truncation: If datagram > buffer, excess data is discarded.
Warning
Buffer Size: Ensure buffer has at least len bytes.

Example: Echo Server

int sock = CreateRxUdpSocket(5000);
uint8_t buf[1500];
IPADDR clientIP;
uint16_t lp, rp;
while (1) {
int n = recvfrom(sock, buf, sizeof(buf), &clientIP, &lp, &rp);
if (n > 0) {
printf("Received %d bytes from %s:%d\r\n",
n, AsciiIP(clientIP).c_str(), rp);
sendto(sock, buf, n, clientIP, rp); // Echo back
}
}
See also
CreateRxUdpSocket(), CreateRxTxUdpSocket(), sendto(), select()

◆ SendFragmentedUdpPacket()

int SendFragmentedUdpPacket ( const IPADDR & to,
uint16_t source_port,
uint16_t dest_port,
puint8_t data,
int length )
inline

#include <udp.h>

Send large UDP packet (>MTU) with IP fragmentation.

Sends a UDP packet that exceeds the Maximum Transmission Unit (MTU) by automatically fragmenting it at the IP layer. The function handles both IPv4 and IPv6 addressing and reassembly is handled by the receiving host.

This is useful for sending large datagrams without implementing application-level fragmentation. However, note that IP fragmentation can reduce reliability since loss of any fragment requires retransmission of the entire datagram.

Parameters
toDestination IP address (IPv4 or IPv6)
source_portSource UDP port number. Use 0 for automatic port assignment (recommended)
dest_portDestination UDP port number
dataPointer to data buffer to send
lengthLength of data in bytes (can exceed MTU)
Returns
Number of bytes sent on success, 0 on failure
Note
IP fragmentation may be blocked by some firewalls and routers
For maximum reliability, consider keeping packets under MTU size (typically 1500 bytes for Ethernet)
This function wraps SendFragmentedUdpPacket6() which handles both IPv4 and IPv6
Warning
Fragmented packets are more susceptible to loss and can impact performance

Example:

IPADDR destination = AsciiToIp("192.168.1.100");
uint8_t largeData[8000]; // Larger than typical MTU
// ... fill largeData ...
int result = SendFragmentedUdpPacket(destination, 0, 5000, largeData, sizeof(largeData));
if (result > 0) {
printf("Sent %d bytes\n", result);
} else {
printf("Send failed\n");
}
See also
SendFragmentedUdpPacket6()
SendUdpPacket() for non-fragmented sending

◆ sendto()

int sendto ( int sock,
puint8_t what_to_send,
int len_to_send,
const IPADDR & to_addr,
uint16_t remote_port )
inline

#include <udp.h>

Send UDP packet through socket to specified destination.

Transmits a UDP datagram through the specified socket to the given IP address and port. This is the standard BSD socket function for sending UDP data. Works with sockets created by CreateTxUdpSocket() or CreateRxTxUdpSocket().

Operation:

  • Sends datagram immediately (non-blocking)
  • No connection establishment required
  • No delivery guarantee (UDP is unreliable)
  • Each call creates a new independent datagram
Parameters
sockSocket file descriptor from CreateTxUdpSocket() or CreateRxTxUdpSocket() Must be a valid socket (>= 0) or behavior is undefined
what_to_sendPointer to data buffer to transmit Buffer content is copied during transmission
len_to_sendNumber of bytes to send from buffer
  • Maximum practical size: 1472 bytes (IPv4) or 1452 bytes (IPv6)
  • Larger sizes may cause IP fragmentation (avoid if possible)
  • Use SendFragmentedUdpPacket() for data > MTU
to_addrDestination IP address (IPv4 or IPv6 based on build configuration) Use AsciiToIp() or AsciiToIp4() to convert from string format
remote_portDestination port number (1-65535) Must match listening port on remote system
Returns
Number of bytes successfully queued for transmission (should equal len_to_send), or negative error code on failure:
  • UDP_ERR_NOTOPEN_TO_WRITE (-2): Socket not configured for sending
  • UDP_ERR_NOSUCH_SOCKET (-1): Invalid socket descriptor
  • Other negative values: System-specific errors
Note
Non-Blocking: This function returns immediately after queuing data. The datagram may not have been physically transmitted yet.
No Delivery Confirmation: UDP provides no acknowledgment. Successfully sending does NOT mean the remote host received the packet. For reliable delivery, implement application-level acknowledgments or use TCP.
Maximum Transfer Unit (MTU): Ethernet MTU is typically 1500 bytes. After UDP (8 bytes) and IP headers (20-40 bytes), safe payload is ~1472 bytes. Exceeding this causes fragmentation, increasing packet loss risk.
Warning
Buffer Validity: Ensure what_to_send buffer remains valid and contains at least len_to_send bytes. Buffer overruns cause undefined behavior.
Socket Type: Using sendto() on receive-only socket (CreateRxUdpSocket()) will fail with UDP_ERR_NOTOPEN_TO_WRITE.

Expand for Example Usage

Examples

Example 1: Simple Send

IPADDR serverIP = AsciiToIp("192.168.1.100");
int sock = CreateTxUdpSocket(serverIP, 8080, 0);
if (sock >= 0) {
const char* msg = "Hello, Server!";
int sent = sendto(sock, (uint8_t*)msg, strlen(msg), serverIP, 8080);
if (sent == strlen(msg)) {
printf("Successfully sent %d bytes\r\n", sent);
} else if (sent < 0) {
printf("Send failed: error %d\r\n", sent);
}
close(sock);
}

Example 2: Send Binary Data

struct SensorData {
uint32_t timestamp;
int16_t temperature;
int16_t humidity;
} data;
data.timestamp = Secs;
data.temperature = ReadTemperature();
data.humidity = ReadHumidity();
IPADDR collector = AsciiToIp("10.0.1.50");
int sock = CreateTxUdpSocket(collector, 5000, 0);
if (sock >= 0) {
int result = sendto(sock, (uint8_t*)&data, sizeof(data),
collector, 5000);
if (result != sizeof(data)) {
printf("Warning: Send incomplete\r\n");
}
close(sock);
}


See also
CreateTxUdpSocket() - Create transmit socket
CreateRxTxUdpSocket() - Create bidirectional socket
sendtovia() - Send via specific network interface
recvfrom() - Receive UDP packets
SendFragmentedUdpPacket() - For sending large datagrams