2016-05-30 15 views
0

Ich mache eine Übung auf IPC mit Rohren. Das Protokoll ist wie folgt:Interprozesskommunikation in C

  1. Client (Kind) liest Dateinamen von stdin
  2. Client sendet Dateinamen über Rohr Server
  3. Server (Eltern) liest Dateinamen aus Rohr
  4. Server erhält Informationen über die Datei (stat sys call)
  5. Server sendet Dateiinformationen über Pipe an Client.
  6. Client liest aus Rohr und Ausgänge Datei info

Ich bin Probleme mit den letzten Schritten stdout ich weiß nicht, wie richtig diese Informationen zu senden. Im Moment ist die Ausgabe vom Client Müll. Hier ist der Code:

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <string.h> 

#define BUFSIZE 1024 

int main() 
{ 
    int fd1[2], fd2[2], pid, n; 
    char buf[BUFSIZE]; 
    pipe(fd1); 
    pipe(fd2); 
    if ((pid = fork()) == 0) 
    { 
     close(fd1[0]); 
     close(fd2[1]); 
     read(STDIN_FILENO, buf, BUFSIZE); // 1. client(child) reads file name from stdin 
     int len = strlen(buf); 
     buf[len - 1] = '\0'; 
     write(fd1[1], buf, len); // 2. client sends file name over pipe to server 
     while ((n = read(fd2[0], buf, BUFSIZE)) > 0) 
     { 
      write (STDOUT_FILENO, buf, n); // 6. client reads file info from pipe and outputs to stdout 
     } 
    } 
    else 
    { 
     struct stat st; 
     close(fd1[1]); 
     close(fd2[0]); 
     read(fd1[0], buf, BUFSIZE); // 3. server (parent) reads file name from pipe 
     stat(buf, &st); // 4. server obtains information about the file (stat sys call) 
     write(fd2[1], (void *)st.st_size, sizeof(st.st_size)); // 5. server file information over pipe to client. 
     write(fd2[1], (void *)st.st_atime, sizeof(st.st_atime)); 
    } 
    return 0; 
} 

Update:

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <string.h> 

#define BUFSIZE 1024 

int main() 
{ 
    int fd1[2], fd2[2], pid; 
    size_t n; 
    char buf[BUFSIZE]; 
    pipe(fd1); 
    pipe(fd2); 
    if ((pid = fork()) == 0) 
    { 
     close(fd1[0]); 
     close(fd2[1]); 
     n = read(STDIN_FILENO, buf, BUFSIZE - 1); // 1. client(child) reads file name from stdin 
     buf[n] = '\0'; 
     write(fd1[1], buf, n); // 2. client sends file name over pipe to server 
     while ((n = read(fd2[0], buf, BUFSIZE)) > 0) 
     { 
      if ((write (STDOUT_FILENO, buf, n)) != n) // 6. client reads file info from pipe and outputs to stdout 
      { 
       perror("client: write error\n"); 
      } 
     } 
    } 
    else 
    { 
     struct stat st; 
     close(fd1[1]); 
     close(fd2[0]); 
     read(fd1[0], buf, BUFSIZE); // 3. server (parent) reads file name from pipe 
     stat(buf, &st); // 4. server obtains information about the file (stat sys call) 
     if (write(fd2[1], (void *)st.st_size, sizeof(st.st_size)) != sizeof(st.st_size)) // 5. server sends file information over pipe to client 
     { 
      perror("server: write error\n"); 
     } 
     if (write(fd2[1], (void *)st.st_atime, sizeof(st.st_atime)) != sizeof (st.st_atime)) 
     { 
      perror("server: write error\n"); 
     } 
    } 
    return 0; 
} 
+0

Sie müssen 'dup' stdin. – Dan

Antwort

0

Sie nicht strlen() hier verwenden können. Sie sollten stattdessen den Rückgabewert von read() verwenden.

Nach read() die Daten in buf ist nichts anderes als eine Sequenz von Bytes, könnte es zu einer Zeichenfolge, wenn Sie ein '\0' Byte am Ende der Sequenz hinzufügen. Da es nicht vorhanden ist, ruft Aufruf strlen()undefined Verhalten, so dass es egal ist, was Sie danach tun, wird es nicht wie erwartet verhalten.

Die strlen() könnte als

Sie Dinge
size_t 
strlen(const char *const string) 
{ 
    size_t length; 
    length = 0; 
    while (string[length] != '\0') 
     ++length; 
    return length; 
} 

ein Grund gedacht werden wie

for (size_t i = 0 ; i < strlen(string) ; ++i) ... 

speziell vermeiden sollten, weil Sie über eine Schleife, wie die in der strlen() Implementierung verwenden können.

ther Rückgabewert von read() Verwenden Sie stattdessen

ssize_t read_length; 
read_length = read(STDIN_FILENO, buf, sizeof(buf) - 1); 

, wenn Sie es sich um eine gültige Zeichenfolge im Sinne machen wollen, dass Sie es zu einem der str* Funktionen passieren kann, einfach

buf[read_length] = '\0'; 

Vergessen Sie nicht, zum Beispiel auf Fehler read_length != -1 zu überprüfen.

+0

Warum? Es wird ein '\ n' von der Eingabe des Benutzers geben, so dass strlen korrekt funktionieren sollte. –

+0

Nein, das '' \ n'' wird 'strlen()' nicht stoppen. –

+0

Es gibt kein '' \ 0'' in der Reihenfolge der vom Benutzer empfangenen Bytes? –