Ошибка UDP C Server sendto(): невозможно назначить запрошенный адрес

Я пишу базовую клиент-серверную программу на C, используя UDP. Идея программы заключается в том, что клиент отправляет сообщение на сервер, сервер получает его, а затем возвращает обратно клиенту (цель состоит в том, чтобы измерить RTT для UDP). К сожалению, на стороне сервера, когда программа пытается вызвать sendto() для отображения сообщения, я получаю сообщение об ошибке «Не удается назначить запрошенный адрес».

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <fcntl.h>

#define SERVER_PORT 7000 
#define MAX_PENDING 10 
#define MAX_LINE 1024000

int main() 
{ 
    struct sockaddr_in sin, sout;
    socklen_t soutLen; 
    char buf[MAX_LINE]; 
    int len;
    int msgLen;
    int s; 
    char *msg;
    if( (s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
        perror("could not establish UDP socket");
        exit(1);
    }

    /* build address data structure */ 
    bzero((char *)& sin, sizeof( sin)); 
    sin.sin_family = AF_INET; 
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(SERVER_PORT);

    if( (bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0){
        perror("udpServer: bind"); 
        exit( 1); 
    }

    while(1){
        if((msgLen = recvfrom(s, buf, sizeof(buf), 0,(struct sockaddr *)&sout, &soutLen))<0){
            perror("udpServer: recvfrom()"); 
            exit( 1); 
        }

        if( (sendto(s, buf, msgLen, 0, (struct sockaddr *)&sout, sizeof(sout)))<0 ){
            perror("udpServer: sendto()"); 
            exit( 1); 
        }
        free(msg);
    }

} 

Заранее спасибо: я новичок в C, поэтому любой совет очень ценится!


person Tom Kreamer    schedule 17.11.2014    source источник


Ответы (1)


Проблема в том, что ваш sout, который вы передаете в sendto, неверен, потому что вы неправильно устанавливаете его размер при передаче в recvfrom:

человек получен от:

 ssize_t
 recvfrom(int socket, void *restrict buffer, size_t length,
          int flags, struct sockaddr *restrict address,
          socklen_t *restrict address_len);

Если address не является нулевым указателем и сокет не ориентирован на соединение, заполняется исходный адрес сообщения. Аргумент address_len является значением. аргумент результата, инициализируемый размером буфера, связанного с адресом, и изменяемый по возвращении, чтобы указать фактический размер хранящегося там адреса.

Когда вы передаете &sout в recvfrom, вы также должны сообщить recvfrom размер структуры, которую вы передаете, чтобы он знал, сколько данных он может туда записать — soutLen является как входным, так и выходным параметром. Поскольку вы не инициализируете soutLen, вероятно, его значение меньше фактического размера структуры, а это означает, что то, что вы получите в sout, недействительно.

Итак, вам нужно инициализировать soutLen:

struct sockaddr_in sin, sout;
socklen_t soutLen = sizeof(sout); 

Затем вы должны передать это значение в качестве размера sendto вместо sizeouf(sout) (это может не требоваться, но это хорошая практика):

   if( (sendto(s, buf, msgLen, 0, (struct sockaddr *)&sout, soutLen))<0 ){

Также, как примечание, вы освобождаете msg, которые вы никогда не выделяли. Это не связано, но может вызвать проблемы позже.

Надеюсь это поможет.

person John Ledbetter    schedule 18.11.2014
comment
Это действительно было проблемой. Спасибо! - person Tom Kreamer; 24.11.2014