2013-08-29 16 views
0

我正在學習FIFO,並且已經編寫了一個迭代服務器,它接受來自多個客戶端的請求。客戶通過寫入服務器上衆所周知的fifo來請求文件。服務器從它的FIFO中讀取數據,並將請求文件的內容放入客戶端讀取的新FIFO中。我運行服務器。當我第一次運行客戶端時,事情按預期工作,客戶端讀取文件的內容。當我第二次運行客戶端時,來自客戶端的消息以前綴字符作爲前綴。我不知道這個退格是從哪裏來的。有任何想法嗎? 這是服務器代碼:退格字符被添加到FIFO中

#include<stdio.h> 
#include<string.h> 
#include<unistd.h> 
#include<errno.h> 
#include<sys/types.h> 
#include<fcntl.h> 
#include<stdlib.h> 
#include"fifo.h" 

#define SERVFIFO "/tmp/fifo.serv" 
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) 

int main(int argc, char** argv) { 
    int readfifo, dummywrite, filefd, writefd, n; 
    int clientpid; 
    char buff[MAXLINE], *spaceptr, fifoname[MAXLINE]; 

    if (mkfifo(SERVFIFO, FILE_MODE) < 0 && errno != EEXIST) { 
     printf("Can't create %s", SERVFIFO); 
    } 

    readfifo = open(SERVFIFO, O_RDONLY, 0); 
    dummywrite = open(SERVFIFO, O_WRONLY, 0); 

    while ((n = Readline(readfifo, buff, MAXLINE)) > 0) { 
     printf("Read data from the fifo:%s and the length is:%d and the character is:%d\n", buff, strlen(buff), buff[0]); 

     if (buff[n - 1] == '\n') { 
      n--; 
      printf("I am also omitting the newline\n"); 
     } 

     buff[n] = '\0'; 
     printf("Buff just after read is:%s and length is %d", buff, strlen(buff)); 

     if ((spaceptr = strchr(buff, ' ')) == NULL) { 
      printf("Bad request from client"); 
      continue; 
     } 

     printf("Found the space:%c\n", *(spaceptr + 1)); 
     *spaceptr++ = '\0'; 
     printf("The value of buffer now is:%s and the length of buffer is:%d and the culprit is %d\n", buff, strlen(buff), *(buff + 0)); 
     clientpid = atol(buff); 
     printf("The client pid is %ld\n", clientpid); 
     snprintf(fifoname, sizeof(fifoname), "/tmp/fifoname.%ld", clientpid); 

     if (mkfifo(fifoname, FILE_MODE) < 0 && errno != EEXIST) { 
      perror("Can't create the fifo"); 
      continue; 
     } 

     printf("Successfully created fifo %s for client\n", fifoname); 

     if ((writefd = open(fifoname, O_WRONLY, 0)) < 0) { 
      printf("Cannot open %s", fifoname); 
      continue; 
     } 

     if ((filefd = open(spaceptr, O_RDONLY, 0)) < 0) { 
      printf("Error opening file\n"); 
      continue; 
     } 
     else { 
      while ((n = read(filefd, buff, MAXLINE))) { 
       write(writefd, buff, n); 
      } 

      close(filefd); 
      close(writefd); 
     } 
    } 
} 

這是客戶端代碼:

#include<stdio.h> 
#include<string.h> 
#include<unistd.h> 
#include<errno.h> 
#include<sys/types.h> 
#include<fcntl.h> 
#include<stdlib.h> 

#define SERVER_FIFO "/tmp/fifo.serv" 
#define MAXLINE 100 
#define MSG "%ld sup.c" 
#define READFIFO "/tmp/fifoname.%ld" 
int main(int argc, char** argv) { 
    int writefifo, readfifo, n; 
    char buff[MAXLINE]; 
    pid_t self_pid = getpid(); 
    printf("Started client with PID:%ld\n", self_pid); 
    writefifo = open(SERVER_FIFO, O_WRONLY, 0); 
    snprintf(buff, sizeof(buff), MSG, self_pid); 
    printf("The message to be written to the server is:%s and the length of the message is %d\n", buff, strlen(buff)); 

    if ((n = write(writefifo, buff, sizeof(buff))) != sizeof(buff)) { 
     perror("Unable to write to server fifo"); 
     exit(0); 
    } 

    printf("Message written to the server; Waiting to read contents\n"); 
    snprintf(buff, sizeof(buff), READFIFO, self_pid); 
    readfifo = open(buff, O_RDONLY, 0); 

    while ((n = read(readfifo, buff, MAXLINE))) { 
     write(STDOUT_FILENO, buff, n); 
    } 

    close(readfifo); 
    close(writefifo); 
    unlink(buff); 
} 
+1

空間是一件美麗的事情... –

+0

感謝您的編輯,但有關這個問題的線索? – user1295872

+0

從先前的運行中可以在FIFO中留下剩餘物嗎?我看到,當FIFO已經存在時,您只需繼續而不是刪除並重新創建。 – ugoren

回答

2

也許這是你真正的計劃,因爲這並不能顯示你的行爲描述的切碎了的版本。幾件事情:

(1)在服務器

readfifo = open(SERVFIFO, O_RDONLY, 0); 
dummywrite = open(SERVFIFO, O_WRONLY, 0); 

我想你知道,如果你打開知名的FIFO沒有的東西在另一端的開放將阻止。這仍然阻止O_RONLY打開,因爲在正常情況下,您將在任何客戶端之前運行服務器。如果你想避免阻塞,只需打開它作爲讀/寫。

(2)在客戶端

snprintf(buff, sizeof(buff), READFIFO, self_pid); 
readfifo = open(buff, O_RDONLY, 0); 

這不是在做你的想法。您的客戶端向服務器的fifo寫入消息,並且服務器使用mkfifo創建客戶端的fifo。由於客戶首先運行fifo不會存在,當你這樣做open。實際上,您試圖以只讀模式打開一個純文件(不存在)。您無法讀取不存在的文件,因此open失敗,但由於您不檢查打開狀態,因此您不知道它。

(3)當你完成它們時取消你的FIFO。

+0

感謝@Duck的迴應。關於第1點,我介紹了虛擬寫入,因爲如果FIFO未打開寫入,則讀取將在服務器的while循環中返回0,我將不得不關閉FIFO並再次打開。 – user1295872

+0

是什麼讓你覺得呢?讀取會阻塞,直到有東西要讀取。 – Duck

+0

關於第2點,它實際上起作用,因爲當我執行打開操作時,它會阻塞,直到服務器打開用於寫入的FIFO。所以這裏開放不會失敗,它會阻止。整個事情在第一個客戶端請求上正常工作。在隨後的請求中,由於「backspace」字符以客戶端請求爲前綴,atol(clientpid)失敗並返回「0」。 – user1295872