Vekktone Official
Vekktone Official

Reputation: 57

recvfrom() hanging after receiving some messages?

I am writing a simple multi-threaded client-server UDP program in C where I send multiple messages at once to the server, and wait for the replies in my receive thread. I'm doing this in order to test the time packets are sent and received.

I have tested locally with my server with 10 packets, and I am correctly receiving all 10 packets, at which point my program terminates.

However, when I test my client with a remote server, my program hangs after I receive about 6 packets. I know the program is hanging on the recvfrom() call, but I don't know why.

I have tried changing the parameters in the call and putting the call in the while loop itself, but to no avail.

Here is my client code:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 
#include <pthread.h>
#include <sys/time.h>

#define SERVER_IP "127.0.0.1"
#define PORT    7851
#define DATA_SIZE 99
#define NUM_MSGS 10

// function declaration for connection handler
void *connection_handler(void *);
struct timeval times[NUM_MSGS][2];

struct sockaddr_in serverAddress; 

int main() { 
    int socketFd; 
    char buf[DATA_SIZE]; 
    //struct sockaddr_in serverAddress; 
    char msg[DATA_SIZE]; 
    int size, numSent;
    time_t timeSent;
    pthread_t threadId;

    // Create the socket 
    if ((socketFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 
        perror("Socket creation failure"); 
        exit(-1);
    } 

    // Initialize server information 
    serverAddress.sin_family = AF_INET; 
    serverAddress.sin_addr.s_addr = inet_addr(SERVER_IP);
    serverAddress.sin_port = htons(PORT); 

    // Print server information
    printf("IP address of server is: %s\n", inet_ntoa(serverAddress.sin_addr));
    printf("Server port is: %d\n", (int) ntohs(serverAddress.sin_port));

    // Create new thread to handle received messages from server
    if (pthread_create(&threadId, NULL, connection_handler, (void *)&socketFd) < 0) {
        perror("Thread creation failure");
        exit(-1);
    }

    numSent = 0;
    int i, j, n;
    for (i = 0; i < NUM_MSGS; i++) {
        // Get current time and create message
        gettimeofday(&times[i][0], NULL);
        n = snprintf(msg, DATA_SIZE, "%d", numSent);
        msg[n] = '\0'; 
        if (n < 0 || n > DATA_SIZE) {
            perror("Message creation failure");
        }

        // Send msg to server
        size = sendto(socketFd, (char *)msg, strlen(msg), 0, (struct sockaddr *) &serverAddress, sizeof(serverAddress)); 

        // Check for sendto error
        if (size == -1) {
            perror("sendto failure");
            exit(-1);
        }

        printf("Client message %d sent.\n", numSent); 
        numSent++;
    }
    // Wait for straggler replies
    sleep(2);

    pthread_join(threadId, NULL);

    //print out times
    for (i = 0; i < NUM_MSGS; i++){
        for (j = 0; j < 2; j++){
            printf("[%d][%d] = [%ld.%06ld]\n", i,  j, (long int)(times[i][j].tv_sec), (long int)(times[i][j].tv_usec));
           }
    }

    close(socketFd); 
    return 0; 
} 


// Connection handler function for new thread created to receive server replies
void *connection_handler(void *newSocketPtr) {
    // cast newSocketPtr to integer ptr then dereference to get the socketFd
    int socketFd = *(int *)newSocketPtr; 
    char buf[DATA_SIZE];
    int addrLen, size;
    int numReceived = 0;
    time_t timeSent, timeReceived, diff, totalTime, avgRTT;

    addrLen = sizeof(serverAddress);
    while ((size = recvfrom(socketFd, (char *)buf, DATA_SIZE, 0, (struct sockaddr *) &serverAddress, &addrLen))!= -1){ // What about when packets get dropped???

        printf("Expecting packet %d\n", numReceived+1);    

        // Check for recvfrom error
        if (size == -1){
            perror("recvfrom failure");
            exit(-1);
        }

        buf[size] = '\0'; 
        // Get current time
        gettimeofday(&times[atoi(buf)][1], NULL);

        printf("Message received from server: %s\n", buf);

        if (numReceived == NUM_MSGS - 1)break;
        numReceived++;
        printf("num received is %d\n", numReceived);   


    }

    close(socketFd);
    pthread_exit(NULL);
}

Upvotes: 0

Views: 327

Answers (1)

alk
alk

Reputation: 70883

[...] tested locally with my server with 10 packets [...] test my client with a remote server, my program hangs after I receive about 6 packets.

UDP simply does not guarantee that packets will be delivered. Your remote server was to slow and missed four packets.

Upvotes: 1

Related Questions