2013-09-21 4 views
1

У меня есть программа c. он сначала пытается отправить сообщение UDP на адрес loopback, а затем читать из loopback. Но сначала функция sendto() завершилась с сообщением «sendto failed: Недопустимый аргумент». код выглядит следующим образом:Как отправить сообщение UDP в адрес loopback, а затем прочитать его?

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <stdio.h> 

int main(void) 
{ 
    struct sockaddr_in servaddr; 
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 

    bzero(&servaddr, sizeof(servaddr)); 

    struct in_addr addr; 
    char dottedaddr[20]; 
    inet_aton("127.0.0.1", &addr); 

     servaddr.sin_family  = AF_INET; 
     servaddr.sin_addr.s_addr = addr.s_addr; 
     servaddr.sin_port  = htons(0); 

    struct sockaddr_in cliaddr; 

     inet_aton("192.168.2.12", &addr); 

     cliaddr.sin_family  = AF_INET; 
     cliaddr.sin_addr.s_addr = addr.s_addr; 
     cliaddr.sin_port  = htons(5000); 


    if(bind(sockfd, (const struct sockaddr *)&cliaddr, sizeof(cliaddr)) == -1) 
    { 
     perror("bind failed"); 
     exit(1); 
    } 

    char buf[] = {'h', 'i', ' ', 'i', ' ', 'l', 'o', 'v', 'e', ' ', 'y', 'o', 'u', 0}; 


    if(sendto(sockfd, buf, sizeof(buf), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) 
    { 
     perror("sendto fails"); 
     exit(2); 
    } 

    fd_set readFd; 
    FD_ZERO(&readFd); 
    FD_SET(sockfd, &readFd); 
    struct timeval timeout; 
    timeout.tv_sec = 5; 
    timeout.tv_usec = 0; 

    int ret = select(sockfd + 1, &readFd, NULL, NULL, &timeout); 
    if(ret > 0) 
    { 
     if(FD_ISSET(sockfd, &readFd)) 
     { 
      char buf2[21]; 
      struct sockaddr_in from; 
      int len = sizeof(from); 
      if(recvfrom(sockfd, buf2, sizeof(buf2), 0, (struct sockaddr *)&from, &len) == -1) 
      { 
       perror("recvfrom fails"); 
      } 
     } 
    } 
    else if (ret == 0) 
    { 
     printf("select time out \n"); 
    } 
    else 
    { 
     printf("select fails"); 
    } 

} 

если я изменить порт сервера от 0 до 5000, затем SendTo() может добиться успеха. Какова причина ?

Второй вопрос заключается в том, что после того, как порт сервера изменен на 5000, select() не может определить, что сокет является удобочитаемым или нет. Это просто тайм-аут. Я думаю, что sockfd должен быть доступен для чтения, так как я просто отправляю сообщение на адрес loopback. Что-то не так с кодом? спасибо!

+0

Привет, вы нашли решение еще? Я также не понимаю, почему адреса сервера и клиента такие ... – Maluvel

ответ

1

Если я изменяю порт сервера от 0 до 5000, то sendto() может преуспеть. Какова причина ?

UDP требуемые пакеты, чтобы иметь конкретный порт источника и назначения больше нуля. Единственным случаем, когда вы можете использовать нулевой порт, является вызов bind; в этом случае сокет будет привязан к некоторому свободному ненулевому порту, а будущие пакеты из этих сокетов будут использовать этот номер как порт src.

Вы всегда должны указывать ненулевой порт назначения в качестве параметра sendto() для пакетов udp.

Я думаю, что sockfd должен быть доступен для чтения, так как я просто отправляю сообщение на адрес loopback.

Я не уверен, но похоже, что вы не слушаете шлейф. Когда вы связываете, вы привязываетесь только к сетевому интерфейсу 192.168.2.12. Вы должны использовать INADDR_ANY для привязки ко всем интерфейсам, включая loopback.