2009-12-12 4 views
1

제 문제는 실제로 매우 격노합니다. 먼저 코드를 보여 드리겠습니다.sendto()가 "성공"오류 코드와 충돌합니다.

/* 
** listener.c -- a datagram sockets "server" demo 
*/ 
//Original Code: Brian Hall ([email protected]) 
//Commented and modified by Vishal Kotcherlakota (PID A07124450) 

#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> 

#define MYPORT "4960" // the port users will be connecting to 
#define YOURPORT "4961" 
#define MAXBUFLEN 10000 

// get sockaddr, IPv4 or IPv6: 
void *get_in_addr(struct sockaddr *sa) 
{ 
    //If the socket address struct says it's an IPv4... 
    if (sa->sa_family == AF_INET) { 
     //...return the IPv4 variable. 
     return &(((struct sockaddr_in*)sa)->sin_addr); 
    } 
    //otherwise, assume it's IPv6, and get the IPv6 variable 
    return &(((struct sockaddr_in6*)sa)->sin6_addr); 
} 

int main(int argc, char *argv[]) 
{ 
    int sockfd, sockfdAck; //socket file descriptor (handle) 
    struct addrinfo hints, *servinfo, *p, *q; 
    int rv; 
    int numbytes; 
    unsigned int seqNum, stateNum=0, ackNum; 
    struct sockaddr_storage their_addr; 
    struct timeval recvTime, timeStamp, latency; 
    char buf[MAXBUFLEN], junk[MAXBUFLEN]; 
    size_t addr_len; 
    char *ackBack; 
    char s[INET6_ADDRSTRLEN]; 

    if (argc != 2) 
    { 
     fprintf(stderr, "usage: <executable> <hostname>\n"); 
     exit(0); 
    } 

    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4 
    hints.ai_socktype = SOCK_DGRAM; 
    hints.ai_flags = AI_PASSIVE; // use my IP 

    if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
     return 1; 
    } 

    // loop through all the results and bind to the first we can 
    for(q = servinfo; q != NULL; q = q->ai_next) { 
     if ((sockfd = socket(q->ai_family, q->ai_socktype, 
       q->ai_protocol)) == -1) { 
      perror("listener: socket"); 
      continue; 
     } 

     if (bind(sockfd, q->ai_addr, q->ai_addrlen) == -1) { 
      close(sockfd); 
      perror("listener: bind"); 
      continue; 
     } 

     break; 
    } 

    if (q == NULL) { 
     fprintf(stderr, "listener: failed to bind socket\n"); 
     return 2; 
    } 

    freeaddrinfo(servinfo); 

    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4 
    hints.ai_socktype = SOCK_DGRAM; 

    if ((rv = getaddrinfo(argv[1], BACKPORT, &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
     return 1; 
    } 

    // loop through all the results and bind to the first we can 
    for(p = servinfo; p != NULL; p = p->ai_next) { 
     if ((sockfdAck = socket(p->ai_family, p->ai_socktype, 
       p->ai_protocol)) == -1) { 
      perror("listener: socket"); 
      continue; 
     } 

     break; 
    } 

    if (p == NULL) { 
     fprintf(stderr, "listener: failed to bind socket\n"); 
     return 2; 
    } 

    freeaddrinfo(servinfo); 
     printf("listener: waiting to recvfrom...\n"); 
    while (1) 
    { 

     addr_len = sizeof their_addr; 
     if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, 
      (struct sockaddr *)&their_addr, &addr_len)) == -1) { 
      perror("recvfrom"); 
      exit(1); 
     } 

     /*printf("listener: got packet from %s\n", 
      inet_ntop(their_addr.ss_family, 
       get_in_addr((struct sockaddr *)&their_addr), 
       s, sizeof s)); 
     printf("listener: packet is %d bytes long\n", numbytes); 
     */ 
     buf[numbytes] = '\0'; 
     sscanf(buf,"%u %s",&seqNum, junk); 
     if (seqNum == stateNum + 1) 
     { 
      stateNum = seqNum; 
      printf("Ok, state is now %u.\n", stateNum); 
     } 
     ackBack = malloc(20*sizeof(char)); 
     sprintf(ackBack, "%u acknowledged\0", stateNum); 
     numbytes = sendto(sockfdAck, ackBack, strlen(ackBack), 0, p->ai_addr, p->ai_addrlen); 
     if (numbytes == -1); 
     { 
      perror("sendto"); 
      exit(1); 
     } 
     free(ackBack); 
    } 

    return 0; 
} 

부주의 한 코드를 용서하십시오. 나는이 임무를 제 시간에 끝내기 위해 필사적으로 노력하고 있습니다. 목표는 데이터 그램 소켓을 사용하여 ARQ 프로토콜을 개발하는 것입니다. 이 코드는 작동해야하지만, 실행할 때 오류 sendto: Success이 발생합니다. 즉, sendto() 호출이 실패했습니다. 어디서나이 문서를 찾을 수 없으며 필사적으로 필사적입니다.

답변

5

bind()에 가지고와는 아무 상관이 없다 -이 구문을 살펴 걸릴 사실 : (당신은 항상 실행 조건없이 다음 몸이없는 상태, 몸이

if (numbytes == -1) ;  // semicolon ! 
{ 
     perror("sendto"); 
     exit(1); 
} 

을 당신이 관찰 할 수있는 것처럼).

numbytes의 printf를 추가하면 오류가 없다는 것을 알 수 있습니다.

이처럼보기 힘든 종류의 오류를 피하려면 일반적으로 조건의 직후에 중괄호를 넣으십시오. 그러면 즉시이를 발견했을 것입니다. 물론 이것은 회사/프로젝트의 코딩 규칙의 문제입니다.

+1

사실은 항상 작은 것들입니다. 너무 감사합니다! –

+0

예, 맞습니다. 너무 빨리 대답했습니다. –

관련 문제