2010-11-29 10 views
1

私はここにシンプルなソケットサーバーを持っていて、私には簡単な質問があるはずです。ソケットが接続を受け入れる前に、プロセス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

あなたが聞く前にprintfを実行した場合、同じ問題がありますか? – Cratylus

答えて

6

printfの呼び出し後fflush(stdout);への呼び出しを追加するか、ラインバッファリングにstdoutを設定するsetvbuf(stdout, NULL, _IOLBF, 0);を使用しています。

+0

あなたは 'setvbuf()'呼び出しで任意のバッファを抑制しました。ほとんどの目的のために、バッファリングされるのではなく、バッファされません。しかし、私は基本的な診断に同意します。これは、デーモン(サーバー)の呼び出し方法に少し依存します。ただし、stdoutが端末に接続されたままではなくファイルに送信されている場合は、正しいです。 –

+0

または同等に 'setlinebuf(stdout)'です。 –

0

あなたには、いくつか試してくださいました:

pid_t pid = getpid(); 

をしてPIDを印刷するには、GDBを使用しよう値? それにもかかわらず、あなたのpidが印刷されるはずです。あなたがしようとした場合:

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

'%ld'は' pid_t'の形式が間違っています。私は、デフォルトの宣伝の後では、 'int'以外の何かのプラットフォームを見たことがありませんでした。 –

+0

@R。 man 2 wait:printf( "子PIDは%ld \ n"、(long)getpid()); – Aif

0

()ブロックを受け入れるが、それは(printf関数に干渉しない)、そしてそれがノンブロッキングそれを助けにはなりません作り、そしてあなたが本当に何をやっている知っている限り、あなたのプログラムの正しい動作を破壊しますノンブロッキングネットワークコード。これはバッファリングの問題でなければなりません:fflush(stout)はそれを修正する必要があります。