recvfrom () зависает после получения некоторых сообщений? - PullRequest
0 голосов
/ 03 ноября 2018

Я пишу простую многопоточную UDP-программу клиент-сервер на C, где я отправляю несколько сообщений одновременно и жду ответов в моем потоке получения. Я делаю это для того, чтобы проверить время отправки и получения пакетов.

Я проверил локально на своем сервере с 10 пакетами, и я правильно получаю все 10 пакетов, после чего моя программа завершается.

Однако, когда я тестирую свой клиент с удаленным сервером, моя программа зависает после получения около 6 пакетов. Я знаю, что программа зависает при вызове recvfrom(), но я не знаю почему.

Я попытался изменить параметры вызова и поместить вызов в сам цикл while, но безрезультатно.

Вот мой код клиента:

#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);
}

1 Ответ

0 голосов
/ 03 ноября 2018

[...] протестировано локально с моим сервером с 10 пакетами [...], тестирует мой клиент с удаленным сервером, моя программа зависает после получения около 6 пакетов.

UDP просто не гарантирует, что пакеты будут доставлены. Ваш удаленный сервер замедлил работу и пропустил четыре пакета.

...