I've modified this C datagram (UDP) socket client example:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#define SERVERPORT "4950"
volatile sig_atomic_t is_shutdown = 0;
void handler_signal(int signal)
{
if (signal == SIGINT)
{
is_shutdown = 1;
}
}
int main(int argc, char *argv[])
{
int socket_fd;
struct addrinfo hints, *server_info, *temp;
int result;
int number_bytes;
if (argc != 2)
{
fprintf(stderr, "usage: executable [hostname]\n");
return 1;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
result = getaddrinfo(argv[1], SERVERPORT, &hints, &server_info);
if (result != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(result));
return 1;
}
// loop through all the results and make a socket
for(temp = server_info; temp != NULL; temp = temp->ai_next)
{
socket_fd = socket(temp->ai_family, temp->ai_socktype, temp->ai_protocol);
if (socket_fd == -1)
{
fprintf(stderr, "socket error: %s\n", strerror(errno));
continue;
}
break;
}
freeaddrinfo(server_info);
if (temp == NULL)
{
fprintf(stderr, "failed to create socket\n");
return 2;
}
//int hostname_length = strlen(argv[2]);
unsigned long counter = 0;
const size_t buffer_length = 50;
char buffer[buffer_length];
memset(&buffer, 0, buffer_length);
while (!is_shutdown)
{
snprintf(buffer, buffer_length, "%lu", counter++);
number_bytes = sendto(socket_fd, buffer, buffer_length, 0, temp->ai_addr, temp->ai_addrlen);
if (number_bytes == -1)
{
fprintf(stderr, "sendto error: %s\n", strerror(errno));
break;
}
printf("sent %d bytes to %s.\n", number_bytes, argv[1]);
}
result = close(socket_fd);
if (result == -1)
{
fprintf(stderr, "close error: %s\n", strerror(errno));
}
printf("exiting application\n");
return 0;
}
It fails on sendto
function with Invalid argument (errno 22)
on the second iteration of the loop. It works on the first.
However, the code works (client keeps sending messages in an infinite loop and server successfully receives them) if I change it to the following:
//...
//create a copy to pass it later
socklen_t length = temp->ai_addrlen;
struct sockaddr *address = temp->ai_addr;
while (!is_shutdown)
{
snprintf(buffer, buffer_length, "%lu", counter++);
number_bytes = sendto(socket_fd, buffer, buffer_length, 0, address, length);
//...
What have I done here? What am I missing? I am not sure what is going on here.