0
votes

I am trying to write a server program that just displays any raw data it receives from anyone through udp. A client can send some data to it at any time. No errors appear except for "Socket error: Resource temporarily unavailable" which in other words mean that recvfrom has no data to receive (because it's presumably not getting any packets).

The client just sends "test!" to 127.0.0.0:12345, while the server listens with a non-blocking socket on port 12345. It may be worth noting that I am on linux.

Why is server not displaying the packets that it's obviously being sent from client? I don't see what I'm missing.

common.h

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>

typedef struct sockaddr_in sockaddr_in;
typedef struct sockaddr sockaddr;

int createSocket(uint16_t port)
{
    int handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    if (handle <= 0)
    {
        printf("failed to create socket\n");
        return 0;
    }

    sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);

    if (bind(handle, (const sockaddr*)&address, sizeof(sockaddr_in)) < 0)
    {
        printf("failed to bind socket\n");
        return 0;
    }

    int nonBlocking = 1;
    if (fcntl(handle, F_SETFL, O_NONBLOCK, nonBlocking) == -1)
    {
        printf("failed to set non-blocking\n");
        return 0;
    }

    return handle;
}

int sendData(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint16_t port, int handle, char* packet_data, int packet_size)
{
    uint32_t address = (a << 24) | (b << 16) | (c << 8) | d;

    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(address);
    addr.sin_port = htons(port);

    int sent_bytes = sendto(handle, (const char*)packet_data, packet_size, 0, (sockaddr*)&address, sizeof(sockaddr_in));

    if (sent_bytes != packet_size)
    {
        printf("failed to send packet (%d/%d)\n", sent_bytes, packet_size);
        return 0;
    }
}

server.c

#include "common.h"
#include <time.h>

void main(void){
    int socket = createSocket(12345);
    if (!socket){
        perror("Socket error");
    }
    int true=1;
    setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (const void*)&true, 1);
    // so that we can immediately reuse the port if the server stops running

    char buffer[100] = "No data";
    if(!listen(socket, 0)){
        perror("Socket error");
    }

    //struct timespec delay = {0,33333333}; // 30Hz
    struct timespec delay = {0,100000000}; // 100Hz

    int running = 1;
    int ret = 0;
    while(running){
        ret = recvfrom(socket, &buffer, 100, 0, NULL, NULL);
        if (ret < 0){
            perror("Socket error");
        } else if (ret > 0){
            printf("%d: %s\n", ret, buffer);
        }

        nanosleep(&delay,NULL); 
    }
}

client.c

#include "common.h"

void main(void){
    int socket = createSocket(0);
    printf("Started client on port %d\n", socket);

    if(!sendData(127,0,0,0,12345, socket, "test!", 5)){
        perror("Socket error");
    } else {
        printf("Sent data.\n");
    }
}
1
Don't call listen for UDP. man listen: "The sockfd argument is a file descriptor that refers to a socket of type SOCK_STREAM or SOCK_SEQPACKET". That is, listen is only for TCP.kaylum
if(!listen(socket, 0)). That check is wrong. 0 means success. So you should check for -1 and you'll see you get an error there.kaylum
perhaps use 127.0.0.1: howtogeek.com/149227/…yano
also consider using inet_aton to convert the string "xxx.xxx.xxx.xxx" ipv4 address to the binary addressyano
@yano turns out you were right! There was another issue that messed the whole thing up. See answer.Heap Overflow

1 Answers

0
votes

I passed a pointer to address where I was supposed to pass a pointer to addr in common.h -> sendTo().

On top of that, I was sending packets to 127.0.0.0 when that should have been 127.0.0.1 (thanks @yano).

Corrected code:

int sendData(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint16_t port, int handle, char* packet_data, int packet_size)
{
    uint32_t address = (a << 24) | (b << 16) | (c << 8) | d;

    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(address);
    addr.sin_port = htons(port);

    int sent_bytes = sendto(handle, (const char*)packet_data, packet_size, 0, (sockaddr*)&addr, sizeof(sockaddr_in));

    if (sent_bytes != packet_size)
    {
        printf("failed to send packet (%d/%d)\n", sent_bytes, packet_size);
        return 0;
    }
}