2010-11-29 13 views
1

Ich habe einen einfachen Socket-Server hier, und was mir scheint, sollte eine einfache Frage sein. Bevor der Socket Verbindungen akzeptiert, möchte ich seine Prozess-ID drucken lassen. Aber es wird nichts gedruckt, egal was es ist, bis es eine Verbindung gibt. Zuerst dachte ich, das war, weil der Anruf annehmen den Druck irgendwie blockiert wurde, damit ich schon versucht, diese Zugabe in verschiedenen Orten:Linux C-Socket-Server printf Problem

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

Aber das hatte keinen Einfluss auf die anderen Code als machen die nicht blockierende akzeptieren. Ich hoffte also, dass jemand hier mir erzählen könnte, was vor sich geht. Der Server funktioniert ansonsten. Ich werde weitermachen und den Client-Code auch posten.

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

Wenn Sie Printf vor dem Anhören haben, haben Sie das gleiche Problem? – Cratylus

Antwort

6

einen Aufruf an fflush(stdout); hinzufügen nach dem Aufruf von printf oder setvbuf(stdout, NULL, _IOLBF, 0); verwenden zu setzen stdout gepufferte Zeile zu.

+0

Sie haben jeden Puffer mit dem Aufruf 'setvbuf()' unterdrückt; Für die meisten Zwecke ist es ungepuffert und nicht gepuffert. Aber ich stimme der Grunddiagnose zu. Es hängt ein bisschen davon ab, wie der Daemon (Server) aufgerufen wird. Wenn jedoch stdout an eine Datei gesendet wird und nicht an ein Terminal angehängt wird, sind Sie richtig. –

+0

Oder äquivalent 'setlinebuf (stdout)'. –

0

Haben Sie versucht, einige:

pid_t pid = getpid(); 

und versuchen gdb zu verwenden pid zu drucken Wert? Trotzdem sollte Ihr Pid drucken. Was passiert, wenn Sie versuchen:

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

'% ld' ist fast sicher ein falsches Format für' pid_t'. Ich habe noch nie eine Plattform gesehen, wo es nach Standard-Promotions (und manchmal auch "kurz") alles andere als "int" war. –

+0

@R. from man 2 wait: printf ("Untergeordnete PID ist% ld \ n", (lang) getpid()); – Aif

0

accept() blockiert, aber es stört printf() nicht, und es nicht blockierend zu machen, hilft nicht und zerstört die korrekte Funktionsweise Ihres Programms, wenn Sie nicht wirklich wissen, was Sie tun mit nicht blockierendem Netzwerkcode. Dies muss ein Pufferproblem sein: fflush (stout) sollte es beheben.