2009-12-12 175 views
1

我的问题实际上相当令人生气。我会先告诉你代码。sendto()崩溃,错误代码为“Success”

/* 
** 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

它确实总是小事情。非常感谢你! – 2009-12-12 11:04:21

+0

是的你是对的,我回答得太快。 – 2009-12-12 12:13:29