我有一项工作,我必须使用fifo将文件从客户端进程转移到服务器进程。我试图将fifo文件作为我们在系统中创建的其他文件来处理。它编译时没有任何错误,但是没有正确执行。有人可以给我一个关于计算机系统内部fifo文件结构的想法吗?到目前为止,我知道如何对fifo文件使用create(),read(),write(),open()函数。此外,如果有人可以帮助我更正,我将不胜感激。我的程序?
我的客户端和服务器程序如下:-
客户端程序:-
#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
int fd;
char *myfifo ="/tmp/myfifo";
char str[80];
FILE *fp;
char filename[20];
printf("\nEnter filename: ");
gets(filename);
mkfifo(myfifo,0666);
fp = fopen(filename,"r");
if(fp == NULL)
{
printf("\nError opening the file");
exit(1);
}
fd = open(myfifo, O_WRONLY);
while(fgets(str,80,fp)!=NULL)
{
write(fd,str,strlen(str)+1);
}
close(fd);
fclose(fp);
return 0;
}
客户端程序:-
#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
int fd1;
char *myfifo ="/tmp/myfifo";
char str1[80], filename[20];
FILE *fp1, *fp2;
fd1= open(myfifo, O_RDONLY);
fp1 = fopen(filename,"r");
fp2 = fopen(filename,"w");
while(!feof(fp1))
{
read(fd1,str1,strlen(str1)+1);
fputs(str1,fp2);
}
return 0;
}
是,但是您的程序中有一些小问题。在第一个:
write(fd, str, strlen(str)+1);
有点不合常规。这会将字符串及其字符串末尾定界符(\ 0)发送到fd中。通常不会使用字符串来执行此操作,strlen(str)可能正是您想要的。
在第二个:
fp1 = fopen(filename,"r");
fp2 = fopen(filename,"w");
文件名尚未分配值,因此这两个打开都几乎肯定会失败。当他们这样做时,它们将返回NULL指针,因此首次尝试使用它们:
while(!feof(fp1))
可能会导致细分冲突。此外,无论如何您都不会使用fp1,因此,如果feof(fp1)返回1,则它将始终返回1。要在fifo用尽时将此循环作为基础,这意味着其中没有数据,没有人拥有它可以写。因此,稍微更改一下该程序将产生:
#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
int fd1;
char *myfifo ="/tmp/myfifo";
char str1[80];
ssize_t n;
fd1= open(myfifo, O_RDONLY);
while ((n=read(fd1,str1,sizeof str1)) > 0)
{
fwrite(str1, 1, n, stdout);
}
return 0;
}
虽然这组更改有效,但是它没有解决您有关将stdio函数与管道一起使用的其他问题。答案是肯定的,这是第二个程序的另一个功能重写:
#include<stdio.h>
int main()
{
char *myfifo ="/tmp/myfifo";
FILE *fp;
int c;
if ((fp = fopen(myfifo, "r")) != NULL) {
while ((c = getc(fp)) != EOF) {
putchar(c);
}
fclose(fp);
}
return 0;
}
此外,也是第一个带有stdio的关键位:
...
FILE *fi = fopen(myfifo, "a");
while(fgets(str,80,fp)!=NULL)
{
fputs(str, fi);
}
fclose(fi);
...
与第二个例子一样,循环可以使用getc,putc实现。一般的改进可能是这样的功能:
ssize_t FCopy(FILE *in, FILE *out) {
int c;
ssize_t len = 0;
while ((c = getc(in)) != EOF) {
len++;
if (putc(c, out) != c) {
return -len;
}
}
return len;
}
ssize_t FileAppend(char *from, char *to) {
FILE *in, *out;
ssize_t n = 0;
if ((in = fopen(from, "rb")) != NULL) {
if ((out = fopen(to, "ab")) != NULL) {
n = FCopy(in, out);
fclose(out);
} else {
n = -1;
}
fclose(in);
} else {
n = -1;
}
return n;
}
所以您的主要对象看起来更像:
...
char filename[80];
printf("Enter a file to store the data in: ");
if (fgets(filename, sizeof filename, stdin)) {
filename[strlen(filename)-1] = '\0';
if (FileAppend(myfifo, filename) < 0) {
printf("Error: could not save data to %s\n", filename);
}
}
....