2011-10-12 56 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中,這將會變得很明顯。 –