Skip to content

Instantly share code, notes, and snippets.

@meowstr
Last active April 30, 2025 22:22
Show Gist options
  • Select an option

  • Save meowstr/ac874701f1cff1a0621567686478a94c to your computer and use it in GitHub Desktop.

Select an option

Save meowstr/ac874701f1cff1a0621567686478a94c to your computer and use it in GitHub Desktop.
posix udp poll based example
#include <arpa/inet.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static struct {
sockaddr local;
int socket;
sockaddr * remote_list;
int remote_count;
} intern;
int init_net( int port )
{
int ret;
intern.remote_list = new sockaddr[ 32 ];
static sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons( port );
addr.sin_addr.s_addr = htonl( INADDR_ANY );
memcpy( &intern.local, &addr, sizeof( sockaddr_in ) );
intern.socket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( intern.socket == -1 ) {
fprintf( stderr, "socket() failed\n" );
return 1;
}
ret = bind( intern.socket, &intern.local, sizeof( sockaddr ) );
if ( ret == -1 ) {
fprintf( stderr, "bind() failed\n" );
return 1;
}
return 0;
}
int add_net_remote( const char * ip, int port )
{
static sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons( port );
addr.sin_addr.s_addr = inet_addr( ip );
int id = intern.remote_count++;
memcpy( intern.remote_list + id, &addr, sizeof( sockaddr_in ) );
return id;
}
void terminate_net()
{
close( intern.socket );
}
int poll_packet( char * buffer, int size, int * source )
{
pollfd info;
info.fd = intern.socket;
info.events = POLLIN;
int ret = poll( &info, 1, 0 );
if ( ret == -1 ) {
fprintf( stderr, "poll() failed\n" );
return -1;
}
if ( ret == 0 ) {
// no events
return 0;
}
socklen_t addr_len = sizeof( sockaddr );
sockaddr addr;
int len = recvfrom( intern.socket, buffer, size, 0, &addr, &addr_len );
// find remote
for ( int i = 0; i < intern.remote_count; i++ ) {
if ( memcmp( &addr, intern.remote_list + i, sizeof( sockaddr ) ) ==
0 ) {
*source = i;
return len;
}
}
// new remote
int id = intern.remote_count++;
memcpy( intern.remote_list + id, &addr, sizeof( sockaddr ) );
*source = id;
return len;
}
int send_packet( int dest, const void * buffer, int size )
{
int ret = sendto(
intern.socket,
buffer,
size,
0,
intern.remote_list + dest,
sizeof( sockaddr )
);
if ( ret == -1 ) {
fprintf( stderr, "sendto() failed\n" );
}
return ret;
}
#pragma once
/// @param port
/// @return 0 on success
int init_net( int port );
void terminate_net();
/// @param ip
/// @param port
/// @return remote id
int add_net_remote( const char * ip, int port );
/// @param buffer
/// @param size
/// @param source remote id of the packet's source
/// @return bytes recieved
int poll_packet( char * buffer, int size, int * source );
/// @param dest remote id of packet's destination
/// @param buffer
/// @param size
/// @return bytes sent
int send_packet( int dest, const void * buffer, int size );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment