2010-11-29 88 views
1

我在這裏有一個簡單的socket服務器,有我認爲應該是一個簡單的問題。在套接字接受連接之前,我希望打印它的進程ID。但是,不管它是什麼,它都不會打印任何東西,除非有連接。起初我以爲這是因爲在接受電話不知何故被卡住打印,所以我嘗試在不同的地方添加此:Linux C服務器的printf問題

int fdflags = fcntl(sockfd, F_GETFL, 0); 
fcntl(sockfd, F_SETFL, fdflags | O_NONBLOCK); 

但是這對不是使接受非阻斷其他的代碼沒有任何影響。所以我希望這裏有人能夠告訴我發生了什麼事。該服務器,否則工作。我會繼續發佈客戶端代碼。

server.c:

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <fcntl.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <signal.h> 
#include <fcntl.h> 

static void error(char *msg) { 
    perror(msg); 
    exit(1); 
} 

static void SIGCHLD_Handler(int sig) { 
    waitpid(-1, NULL, WNOHANG); 
} 

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

    int num,sockfd, newsockfd, portno, clilen; 
    char buffer[256]; 
    struct sockaddr_in serv_addr, cli_addr; 
    struct sigaction sigact; 

    sigact.sa_handler = SIGCHLD_Handler; 
    if (sigaction(SIGCHLD, &sigact, 0)) error("sighandle def"); 

    int n, childPid; 
    if (argc < 2) { 
     fprintf(stderr,"ERROR, no port provided\n"); 
     exit(1); 
    } 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    if (sockfd < 0) error("ERROR opening socket"); 
    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    portno = atoi(argv[1]); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port = htons(portno); 
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding"); 
    listen(sockfd,5); 
    clilen = sizeof(cli_addr); 
    printf("I am the Knock Knock server and my pid number is %d\n", getpid()); 

    while (1) { 
     newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); 
     if (newsockfd < 0) else error("ERROR on accept"); 

     bzero(buffer,256); 

     childPid = fork(); 
     if (childPid < 0) error ("ERROR on fork"); 
     else if (childPid == 0) { 
      close(sockfd); 

      while(1) { 
       // read an int from the client that says how big the message will be 
       n = read(newsockfd, &num, sizeof(int)); 
       // if client sends just Enter, then quit 
       if(num==2) break; 

       // read num bytes from client 
       n = read(newsockfd,buffer,num); 
       if (n < 0) error("ERROR reading from socket"); 

       // display the message from the client 
       printf("Here is the message: %s\n",buffer); 
       num=19; 

       // Tell the client to expect 19 bytes 
       n = write(newsockfd, &num, sizeof(int)); 
       // Send client 19 bytes 
       n = write(newsockfd,"I got your message",num); 
       if (n < 0) error("ERROR writing to socket"); 
      } 

      exit(0); 
     } else close(newsockfd); 
    } 
    return 0; 
} 

client.c:

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

void error(char *msg) { 
    perror(msg); 
    exit(0); 
} 

int main(int argc, char *argv[]) { 
    int num, sockfd, portno, n; 
    struct sockaddr_in serv_addr; 
    struct hostent *server; 

    char buffer[256]; 
    if (argc < 3) { 
     fprintf(stderr,"usage %s hostname port\n", argv[0]); 
     exit(0); 
    } 
    portno = atoi(argv[2]); 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
     error("ERROR opening socket"); 
    server = gethostbyname(argv[1]); 
    if (server == NULL) { 
     fprintf(stderr,"ERROR, no such host\n"); 
     exit(0); 
    } 
    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET; 
    bcopy((char *)server->h_addr, 
     (char *)&serv_addr.sin_addr.s_addr, 
     server->h_length); 
    serv_addr.sin_port = htons(portno); 
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) 
     error("ERROR connecting"); 

    do{ 
     printf("Please enter the message: "); 
     bzero(buffer,256); 
     fgets(buffer,255,stdin); 

     num = strlen(buffer)+1; 
     // send server an int that says how long the coming message will be 
     n = write(sockfd, &num, sizeof(int)); 
     // num=2 when user just presses Enter. No message = quit 
     if(num==2) break; 

     // send server the message (num bytes long) 
     n = write(sockfd,buffer,num); 
     if (n < 0) 
      error("ERROR writing to socket"); 
     bzero(buffer,256); 

     // read how many bytes are coming from the server 
     n = read(sockfd, &num, sizeof(int)); 
     // read num bytes from the server 
     n = read(sockfd,buffer,num); 
     if (n < 0) 
      error("ERROR reading from socket"); 
     // display the message from the server 
     printf("%s\n",buffer); 
    }while(1); 

    return 0; 
} 
+0

如果您在執行listen之前先printf,是否也有同樣的問題? – Cratylus 2010-11-29 07:12:46

回答

0

你嘗試一些:

pid_t pid = getpid(); 

,並嘗試使用gdb輸出PID值? 不過,你的pid應該打印。如果你嘗試什麼:

printf("pid = %ld\n", getpid()); 
+0

`%ld`幾乎肯定是`pid_t`格式不正確。我從來沒有看到過一個平臺,它在默認促銷後(而且之前有時是「短」),除了「int」之外什麼都沒有。 – 2010-11-29 14:00:39

+0

@R。 from man 2 wait:printf(「Child PID is%ld \ n」,(long)getpid()); – Aif 2010-11-29 19:02:11

0

accept()塊,但它不會干擾printf(),並且使其非阻塞無助於此,並且會破壞程序的正確工作,除非您真的知道自己在做什麼與非阻塞網絡代碼。這肯定是一個緩衝問題:fflush(stout)應該修復它。