2011-10-12 52 views
1

everyone。我正在做我的使用UDP建立一个whois服务。无论我在执行代码时遇到问题。BSD C绑定()到UDP挂起的套接字

这里是我的代码:

#include <stdlib.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <pwd.h> 
#include <arpa/inet.h> 
#include <string.h> 

/* 
* Program:  whoisserver 
* 
* Purpose:  UNIX application program act as a server for the "whois" 
*    service on the local machine.    
* 
* Usage:  whois hostname username 
*/ 

#define MSG_LEN   1024 
void whois(int sock); 

int main(int argc,char *argv[]){ 

    int s; /* Socket descriptors */ 
    struct sockaddr_in local_addr; 
    struct hostent *hp; 

    char *myname; 
    myname = argv[0];// copy program name to name 
    printf("This is program: %s \n", myname); 


    /* 
    * Create a socket 
    * Address Family (AF_INET) 
    * UDP (SOCK_DGRAM) 
    */ 
    printf("-Allocating socket for incomming connections...\n"); 
    if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ 
     perror("socket"); 
     exit(1); 
    } 


    /* 
     Set Up local Address 
      address_family (AF_INET) 
      IP address (INADDR_ANY) ? 
      port number (use 6087 by default) 
    */ 
    local_addr.sin_port = 54020; 
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    local_addr.sin_family = AF_INET; 


    /* 
     Bind the socket to the service port 
    */ 

    printf("-Binding Service to Socket...\n"); 
    int n = bind(s, (struct sockaddr *)&local_addr, sizeof local_addr); 
    if(n <0){ 
     perror("bind"); 
     printf("Problem in binding\n"); 
     exit(1); 
    } 

    printf("-Waiting for incomming connection..."); 
    whois(s);// Call whois 
    return(0); 

} 

/* 
    whois function 
    param: int s 
      Socket Descriptor 
*/ 

void whois(int sock){ 
    int len, t; 
    char bufin[MSG_LEN]; 

    struct sockaddr_in remote_addr; 

    // Get the size of remote address  
    len = sizeof(remote_addr); 


    // Infinity loop 

    while(1){ 
     struct passwd *p; 

     // recvfrom while waiting for new customers 
     if((t = recvfrom(sock, bufin, MSG_LEN, 0, 
     (struct sockaddr *) &remote_addr, &len))<0){ 
      perror("recvfrom");  
      exit(0);   
     } 
     bufin[t] = '\0'; // end of string 

     if((p = getpwnam(bufin)) == NULL) 
       strcpy(bufin, "-- This is the result from Gang's server ---\nUser not found\n"); 
     else{ 
      /*Find passwd in pwd.h file. Here is the structure: 

       struct passwd { 
        char *pw_name; 
        char *pw_passwd; 
        uid_t pw_uid; 
        gid_t pw_gid; 
        char *pw_age; 
        char *pw_comment; 
        char *pw_gecos; 
        char *pw_dir; 
        char *pw_shell; 
       }; 
       */ 

     // Print out all the field 
     sprintf(bufin, "-- This is the result from Gang's server ---\nUsername: %s\nPassword: %s\nAge: %s\nUID: %d\nGID: %d\nGECOS: %s\nDIR: %s\nSHELL: %s\nComment: %s\n", 
       p->pw_name, 
       p->pw_passwd, 
       p->pw_age, 
       p->pw_uid, 
       p->pw_gid, 
       p->pw_gecos, 
       p->pw_dir, 
       p->pw_shell, 
       p->pw_comment 
      ); 
     } 
     sendto(sock, bufin, strlen(bufin), 0, (struct sockaddr *)&remote_addr, len); 
    }   
} 

程序停止在绑定地址插座。下面是输出:

{506}paradox:client_server$ a.out 
This is program: a.out 
-Allocating socket for incomming connections... 
-Binding Service to Socket... 
^Z 
[1]+ Stopped     a.out 

我想不出有什么原因。顺便说一下,我使用的是gcc 3.4.3。我也在Mac和Ubuntu上试了一下。同样的结果。

回答

3

似乎停止的原因是因为标准输出是按行缓冲默认情况下,你不会在此消息的末尾有一个换行符:

printf("-Waiting for incomming connection..."); 

添加\n到该消息的结尾,您可能会发现它在recvfrom()呼叫中被阻止。

+0

太棒了!它解决了! –

+0

ktrace和strace工具可以帮助调试这种情况。他们肯定会显示bind()和printf()成功完成,因此您可以搜索真正的问题:为什么日志消息不会出现在屏幕上。 – blaze

0

有你应该改变几件事情:

  • 在设置LOCAL_ADDR的成员,尝试memset(&local_addr, 0, sizeof(local_addr));这样,你确保一切适当初始化。
  • 设置端口时,使用local_addr.sin_port = htons(54020);端口也必须按网络顺序。
+0

感谢您的提及。但仍然没有工作。同样的结果。它在绑定中有任何限制吗?如果我运行代码两次,它可以退出“正在使用的端口”,这是正常的。但我不能让它正常绑定到套接字。我只坚持绑定。没有更多的步骤。 –

+0

我认为其他答案是你真正的问题。你仍然应该使用htons和memset,但是一旦你将\ n添加到你的printf中,这将会变得很明显。 –