退格字符被添加到 FIFO
Posted
技术标签:
【中文标题】退格字符被添加到 FIFO【英文标题】:Backspace character gets added in FIFO 【发布时间】:2013-08-29 03:28:52 【问题描述】:我正在学习 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);
【问题讨论】:
空间是一种美丽的东西...... 感谢您的编辑,但有任何关于该问题的线索吗? FIFO 中会不会有上次运行的剩余物?我看到当 FIFO 已经存在时,您只需继续,而不是删除并重新创建。 客户端向服务器写入 100 个字节,尽管它只初始化了前十个左右的字节。您得到的退格键很可能是由于缺乏数据初始化而导致的巧合。客户端可能应该创建自己的 FIFO 并告诉服务器 FIFO 的名称是什么。服务器有一个众所周知的 FIFO 名称,因此任何进程都可以与之对话。从客户端到服务器的消息应该包含打开客户端创建的 FIFO 所需的信息。 【参考方案1】:也许这是您的真实程序的切碎版本,因为它不会显示您描述的行为。有几点:
(1) 在服务器中
readfifo = open(SERVFIFO, O_RDONLY, 0);
dummywrite = open(SERVFIFO, O_WRONLY, 0);
我假设您知道,如果您打开众所周知的 fifo,而另一端没有任何东西,则 open 将阻塞。这仍然会阻止 O_RONLY 打开,因为在正常情况下,您将在任何客户端之前运行服务器。如果您想避免阻塞,只需将其以读/写方式打开一次。
(2) 在客户端
snprintf(buff, sizeof(buff), READFIFO, self_pid);
readfifo = open(buff, O_RDONLY, 0);
这不是你想的那样。您的客户端向服务器的 fifo 写入一条消息,服务器使用mkfifo
创建客户端的 fifo。由于客户端首先运行,所以当你这样做open
时,fifo 将不存在。实际上,您正在尝试以只读方式打开一个普通文件(不存在)。您无法读取不存在的文件,因此 open
失败,但由于您不检查打开状态,因此您不知道它。
(3) 使用完 FIFO 后取消它们的链接。
【讨论】:
感谢@Duck 的回复。关于第 1 点,我介绍了 dummywrite,因为如果 FIFO 没有为写入而打开,那么读取将在服务器的 while 循环中返回 0,我将不得不关闭 FIFO 并再次调用 open。 是什么让你这么想?读取将阻塞,直到有东西要读取。 关于第2点,它确实有效,因为当我打开时,它会阻塞,直到服务器打开FIFO进行写入。所以这里的 open 不会失败,它会阻塞。整个事情在第一个客户请求时工作正常。在随后的请求中,由于客户端请求的前缀为“退格”字符,因此 atol(clientpid) 失败并返回“0”。 如果在对空 FIFO 的读取调用之前 FIFO 未打开以进行写入,则读取返回 0。如果有先前的描述符打开以进行写入,则阻塞。这是我在理论上学到的,我对此非常确定。如果我没有打开 dummywrite,我检查了第一个客户端发送请求后 while 循环是否退出。这是一个迭代服务器,当 FIFO 中没有数据时,我需要它保持阻塞。如果我在这里错了,请纠正我。 打开服务器fifo进行写入的原因是总是有一个写入器——服务器本身。这可以防止服务器在所有客户端都关闭时没有收到 EOF。因为服务器永远不会看到 EOF,所以它不必一直关闭并重新打开。以上是关于退格字符被添加到 FIFO的主要内容,如果未能解决你的问题,请参考以下文章