How to Get Sender IP from Incoming UDP Packet

Retrieving the sender’s IP address from an incoming UDP packet is a standard network programming task handled directly at the socket layer. Because UDP is a connectionless protocol, the receiving socket does not maintain an active connection with the client; instead, the underlying operating system inspects the IP header of each incoming datagram and exposes the source address via socket reading APIs. This guide demonstrates how to extract the sender’s IP address and port across several popular programming languages, including Python, Node.js, C, and Go.

Python

In Python, the built-in socket module provides the recvfrom() method, which returns both the incoming data buffer and a tuple containing the sender’s IP address and port number.

import socket

# Create a UDP socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('0.0.0.0', 8080))

print("Listening for incoming UDP packets on port 8080...")

while True:
    # recvfrom returns (data, (sender_ip, sender_port))
    data, (sender_ip, sender_port) = server_socket.recvfrom(1024)
    
    print(f"Received message from {sender_ip}:{sender_port}")
    print(f"Data: {data.decode('utf-8', errors='ignore')}")

Node.js

Node.js uses the native dgram module to handle UDP communication. When a message arrives, the 'message' event provides an rinfo (remote info) object containing the sender’s metadata.

const dgram = require('dgram');
const server = dgram.createSocket('udp4');

server.on('message', (msg, rinfo) => {
    // rinfo contains address, family, port, and size
    const senderIp = rinfo.address;
    const senderPort = rinfo.port;
    
    console.log(`Received packet from ${senderIp}:${senderPort}`);
    console.log(`Message: ${msg.toString()}`);
});

server.bind(8080, () => {
    console.log('UDP server listening on port 8080');
});

C (POSIX Sockets)

In C and C++, you pass a pointer to a sockaddr_in structure into the POSIX recvfrom() system call. The kernel fills this structure with the client’s information, which you convert into a human-readable string using inet_ntop().

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>

int main() {
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);
    char buffer[1024];
    char sender_ip[INET_ADDRSTRLEN];

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(8080);

    bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));

    printf("Waiting for UDP packet on port 8080...\n");

    ssize_t bytes_received = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0,
                                      (struct sockaddr*)&client_addr, &client_len);

    if (bytes_received >= 0) {
        buffer[bytes_received] = '\0';
        
        // Convert the binary IP address to a string
        inet_ntop(AF_INET, &(client_addr.sin_addr), sender_ip, INET_ADDRSTRLEN);
        int sender_port = ntohs(client_addr.sin_port);

        printf("Received packet from %s:%d\n", sender_ip, sender_port);
        printf("Payload: %s\n", buffer);
    }

    close(sockfd);
    return 0;
}

Go

Go’s standard net package provides the ReadFromUDP method on a *net.UDPConn instance. This returns the number of bytes read and a *net.UDPAddr struct containing the remote address.

package main

import (
    "fmt"
    "net"
)

func main() {
    addr := net.UDPAddr{
        Port: 8080,
        IP:   net.ParseIP("0.0.0.0"),
    }

    conn, err := net.ListenUDP("udp", &addr)
    if err != nil {
        panic(err)
    }
    defer conn.Close()

    fmt.Println("Listening for UDP packets on port 8080...")

    buffer := make([]byte, 1024)

    for {
        // ReadFromUDP returns the number of bytes and the remote UDPAddr
        n, remoteAddr, err := conn.ReadFromUDP(buffer)
        if err != nil {
            fmt.Println("Error reading:", err)
            continue
        }

        senderIP := remoteAddr.IP.String()
        senderPort := remoteAddr.Port

        fmt.Printf("Received %d bytes from %s:%d\n", n, senderIP, senderPort)
        fmt.Printf("Data: %s\n", string(buffer[:n]))
    }
}