2013-08-29 87 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