BSD-style socket functions for UDP communication.
More...
|
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.
|
|
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:
- Receive-only sockets: Listen for incoming packets on a specific port
- Transmit-only sockets: Send packets to a specific destination
- Bidirectional sockets: Combined receive and transmit capabilities
Key Concepts
Socket Types
1. Receive-Only Socket (Server/Listener)
- Created with CreateRxUdpSocket()
- Binds to local port to receive packets
- Can receive from any sender
- Typical use: Servers, listeners, broadcast receivers
2. Transmit-Only Socket (Client/Sender)
- Created with CreateTxUdpSocket()
- Optionally binds to specific local port
- Sends to predefined destination
- Typical use: Clients, sensors, periodic transmitters
3. Bidirectional Socket (Request/Response)
- Created with CreateRxTxUdpSocket()
- Combines both receive and transmit
- Binds local port and sets remote endpoint
- Typical use: Client-server patterns, RPC-style communication
Port Number Selection
Local Port (Binding)
- 0: System assigns ephemeral port (49152-65535) - recommended for clients
- 1-1023: Well-known ports (e.g., 53=DNS, 123=NTP) - requires privileges
- 1024-49151: Registered ports - typical for custom servers
- 49152-65535: Dynamic/private ports - ephemeral port range
Remote Port (Destination)
- Specify the destination service port
- Must match the listening port on remote system
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) {
if (sock < 0) {
printf("Failed to create socket: %d\r\n", sock);
return;
}
uint8_t buffer[1024];
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);
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) {
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);
}
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) {
if (sock < 0) return -1;
sendto(sock, (uint8_t*)request, strlen(request), serverIP, 6000);
fd_set readfds;
struct timeval tv = {5, 0};
if (
select(sock + 1, &readfds, NULL, NULL, &tv) > 0) {
uint16_t localPort, remotePort;
int n =
recvfrom(sock, (uint8_t*)response, maxLen,
&srcIP, &localPort, &remotePort);
return n;
}
return 0;
}
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
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);
}
}
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");
if (sock >= 0) {
uint8_t discover[] = "DISCOVER:NetBurner";
sendto(sock, discover,
sizeof(discover), broadcastAddr, 9999);
uint8_t buf[256];
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());
}
}
}
- Pattern 6: Using select() for Multiple Sockets
void MultiSocketHandler() {
int maxfd = (sock1 > sock2) ? sock1 : sock2;
fd_set readfds;
uint8_t buffer[512];
uint16_t lp, rp;
while (1) {
if (
select(maxfd + 1, &readfds, NULL, NULL, NULL) > 0) {
int n =
recvfrom(sock1, buffer,
sizeof(buffer),
&srcIP, &lp, &rp);
printf("Port 5000: %d bytes\r\n", n);
}
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:
- **>= 0**: Valid socket file descriptor
- **< 0**: Error code (see UDP_ERR_* constants)
Common error codes:
- UDP_ERR_NOSUCH_SOCKET (-1): Socket does not exist or was closed
- UDP_ERR_NOTOPEN_TO_WRITE (-2): Socket not configured for sending
- UDP_ERR_NOTOPEN_TO_READ (-3): Socket not configured for receiving
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
- Each socket should be used by a single task
- Multiple tasks can use different sockets
- Sockets are NOT thread-safe for concurrent access
- Use separate sockets per task for parallel operations
void Task1(void* pd) {
}
void Task2(void* pd) {
}
Performance Considerations
Buffer Sizing
- Typical MTU: 1500 bytes (Ethernet)
- UDP header overhead: 8 bytes
- IP header overhead: 20 bytes (IPv4), 40 bytes (IPv6)
- Safe payload size: 1472 bytes (IPv4), 1452 bytes (IPv6)
- Larger packets: Use SendFragmentedUdpPacket() for automatic fragmentation
Optimization Tips
- Reuse sockets: Create once, use many times
- Batch operations: Send multiple packets before context switch
- Appropriate buffer sizes: Match expected packet sizes
- Interface binding: Reduce routing overhead in multi-homed systems
- 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
IPADDR destIP = AsciiToIp(
"2001:db8::1");
IPADDR destIP = AsciiToIp(
"192.168.1.100");
#else
#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)
int sock = CreateTxUdpSocketVia(destIP, 8080, 0, 1);
Interface IP Address (Alternative)
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:
- Porting existing socket-based code
- Writing in C (not C++)
- Need select()/poll() integration
- Familiar with Berkeley sockets
- Simple send/receive patterns
When to Use UDPPacket:
- New C++ development
- Need automatic memory management
- Direct buffer manipulation
- Multiple destination sends
- OS_FIFO-based architectures
Advanced Features
Large Packet Transmission (Fragmentation)
For packets exceeding MTU, use SendFragmentedUdpPacket():
uint8_t largeData[5000];
destIP,
0,
8080,
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:
- Increased packet loss risk (one fragment lost = entire packet lost)
- Additional processing overhead
- Potential firewall/router issues
- Better to design protocol with smaller messages when feasible
Socket Lifecycle Management
if (sock < 0) {
return;
}
Common Pitfalls
[NO] Not checking return values
recvfrom(sock, buf, len, &ip, &lp, &rp);
[YES] Always validate
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);
[YES] Match buffer size
uint8_t buf[1500];
int n =
recvfrom(sock, buf,
sizeof(buf), &ip, &lp, &rp);
if (n > 0 && n < sizeof(buf)) {
}
[NO] Ignoring recvfrom() return value
uint8_t buf[512];
recvfrom(sock, buf,
sizeof(buf), &ip, &lp, &rp);
printf("%s", buf);
[YES] Check bytes received
uint8_t buf[512];
int n =
recvfrom(sock, buf,
sizeof(buf), &ip, &lp, &rp);
if (n > 0) {
buf[n] = '\0';
printf("%s", buf);
}
[NO] Port conflicts
[YES] Unique ports or reuse pattern
Debugging Tips
- Enable diagnostics: Call EnableSystemDiagnostics() in UserMain()
- Check socket descriptor: Valid sockets are >= 0
- Verify network connectivity: Ensure interface is up and configured
- Monitor packet capture: Use Wireshark to inspect actual traffic
- 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 ```
- Check firewall rules: Ensure UDP traffic is not blocked
- Validate addresses: Use AsciiIP() to print addresses for debugging
Related Topics
◆ 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_addr | Destination IP address for sending packets Use AsciiToIp() or AsciiToIp4() to convert from string |
send_to_remote_port | Destination port number for sending (1-65535) |
local_port | Local 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");
if (sock < 0) return false;
uint8_t query[512];
int queryLen = BuildDnsQuery(query, hostname);
sendto(sock, query, queryLen, dnsServer, 53);
fd_set readfds;
struct timeval tv = {5, 0};
if (
select(sock + 1, &readfds, NULL, NULL, &tv) > 0) {
uint8_t response[512];
uint16_t lp, rp;
int n =
recvfrom(sock, response,
sizeof(response),
&srcIP, &lp, &rp);
if (n > 0) {
*result = ParseDnsResponse(response, n);
return true;
}
}
return false;
}
Example 2: Echo Client with Response
void EchoClientTest() {
IPADDR serverIP = AsciiToIp(
"192.168.1.100");
if (sock < 0) {
printf("Socket creation failed\r\n");
return;
}
const char* msg = "Hello, Server!";
sendto(sock, (uint8_t*)msg, strlen(msg), serverIP, 5000);
printf("Sent: %s\r\n", msg);
uint8_t buf[256];
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);
}
}
Example 3: Persistent Connection Pattern
void RequestResponseLoop() {
IPADDR serverIP = AsciiToIp(
"10.0.0.50");
if (sock < 0) return;
uint8_t request[64];
uint8_t response[256];
uint16_t lp, rp;
for (int i = 0; i < 10; i++) {
int reqLen = sprintf((char*)request, "REQ:%d", i);
sendto(sock, request, reqLen, serverIP, 6000);
int n =
recvfrom(sock, response,
sizeof(response),
&respIP, &lp, &rp);
if (n > 0) {
response[n] = '\0';
printf("Response %d: %s\r\n", i, response);
}
}
}
#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_port | Local 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) {
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];
uint16_t localPort, remotePort;
while (1) {
int n =
recvfrom(sock, buffer,
sizeof(buffer),
&clientIP, &localPort, &remotePort);
if (n > 0) {
buffer[n] = '\0';
printf("Received %d bytes from %s:%d: %s\r\n",
n, AsciiIP(clientIP).c_str(), remotePort, buffer);
}
}
}
Example 2: Echo Server
void UdpEchoServer() {
if (sock < 0) return;
uint8_t buf[512];
uint16_t lp, rp;
while (1) {
int n =
recvfrom(sock, buf,
sizeof(buf), &srcIP, &lp, &rp);
if (n > 0) {
printf("Echo server received: %d bytes\r\n", n);
}
}
}
Example 3: Broadcast Receiver
void BroadcastListener() {
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];
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_addr | Destination IP address (IPv4 or IPv6 depending on build config) Use AsciiToIp() or AsciiToIp4() to convert from string |
remote_port | Destination port number (1-65535) Must match the listening port on remote system |
local_port | Local 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");
if (sock < 0) {
printf("Failed to create socket\r\n");
return;
}
int sent =
sendto(sock, (uint8_t*)message, strlen(message),
serverIP, 8080);
if (sent > 0) {
printf("Sent %d bytes\r\n", sent);
}
}
Example 2: Periodic Sensor Data Transmission
void SensorTransmitTask(void* pd) {
IPADDR serverIP = AsciiToIp(
"10.0.1.50");
if (sock < 0) return;
char msgBuf[64];
while (1) {
int temperature = ReadTemperatureSensor();
int humidity = ReadHumiditySensor();
int len = sprintf(msgBuf, "TEMP:%d,HUM:%d",
temperature, humidity);
sendto(sock, (uint8_t*)msgBuf, len, serverIP, 5000);
}
}
Example 3: Syslog Client
void SendSyslogMessage(const char* msg, int severity) {
IPADDR syslogServer = AsciiToIp(
"192.168.1.10");
if (sock >= 0) {
char syslogMsg[512];
int len = sprintf(syslogMsg, "<%d>%s", severity, msg);
sendto(sock, (uint8_t*)syslogMsg, len, syslogServer, 514);
}
}
Example 4: Multiple Destinations (Create Multiple Sockets)
void SendToMultipleServers() {
IPADDR server1 = AsciiToIp(
"192.168.1.10");
IPADDR server2 = AsciiToIp(
"192.168.1.20");
uint8_t data[] = "Status update";
if (sock1 >= 0) {
sendto(sock1, data,
sizeof(data), server1, 8080);
}
if (sock2 >= 0) {
sendto(sock2, data,
sizeof(data), server2, 8080);
}
}
- 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
-
sock | Socket file descriptor from CreateRxUdpSocket() or CreateRxTxUdpSocket() |
buffer | Destination buffer for received data |
len | Maximum 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
uint8_t buf[1500];
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);
}
}
- 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
-
to | Destination IP address (IPv4 or IPv6) |
source_port | Source UDP port number. Use 0 for automatic port assignment (recommended) |
dest_port | Destination UDP port number |
data | Pointer to data buffer to send |
length | Length 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];
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
-
sock | Socket file descriptor from CreateTxUdpSocket() or CreateRxTxUdpSocket() Must be a valid socket (>= 0) or behavior is undefined |
what_to_send | Pointer to data buffer to transmit Buffer content is copied during transmission |
len_to_send | Number 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_addr | Destination IP address (IPv4 or IPv6 based on build configuration) Use AsciiToIp() or AsciiToIp4() to convert from string format |
remote_port | Destination 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");
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);
}
}
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");
if (sock >= 0) {
int result =
sendto(sock, (uint8_t*)&data,
sizeof(data),
collector, 5000);
if (result != sizeof(data)) {
printf("Warning: Send incomplete\r\n");
}
}
- 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