我正在尝试使用命名管道(fifo)在C语言中编写代码,客户端在其中询问有关目录的信息。
服务器检查目录的存在,并发回目录的大小以及文件和子目录的数量。该请求还可以指定获取文件和子目录的名称。
客户端将目录的名称作为参数,也将由-d
选项指定。服务器执行Shell脚本以解决问题。
我已经问过有关此主题的问题,并且对代码进行了一些改进,但仍然无法使其正常运行。
这里是问题的链接:How to pass multiple arguments to client (fifo)?
我的问题是,服务器仅打印出一个文件名,而不打印出作为客户端参数的目录内的所有文件名和子目录。
这是修改后的服务器代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "header.h"
int f;
Message msg;
int main() {
if (mkfifo(FIFONAME, S_IFIFO | 0666) < 0) { /*Creating server fifo*/
perror("Failed creating own fifo");
printf("Server: Failed creating fifo_%d file\n", getpid());
unlink(FIFONAME);
exit(1);
}
if ((f = open(FIFONAME, O_RDONLY)) < 0) {
perror("Failed opening fifo");
unlink(FIFONAME);
exit(1);
}
printf("Server is working\n");
while (1) { /*Infinite loop, waiting for client requests*/
if ((read(f, &msg, sizeof(msg)))) {
if (strcmp(msg.dir, "exit") == 0) {
close(f);
unlink(FIFONAME);
exit(1);
}
switch (fork()) {
case -1: {
perror("Fork error\n");
exit(1);
}
case 0: {
char command[MAXLEN];
sprintf(command,"./shell.sh %s %s", msg.dir, msg.spec);
FILE *g;
if ((g = popen(command, "r")) == NULL) {
perror("Popen error");
exit(1);
}
fgets(msg.dir, MAXLEN, g);
fgets(msg.spec, MAXLEN, g);
char result[MAXLEN];
sprintf(result, "fifo_%d", msg.pid);
msg.pid = getpid();
int op;
op = open(result, O_WRONLY);
write(op, &msg, sizeof(msg));
close(op);
exit(0);
}
}
}
}
return 0;
}
和客户端代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "header.h"
int f, fc;
Message msg;
char fifoname[MAXLEN];
int main(int argc, char *argv[]) {
if (argc == 1) {
printf("Usage: %s directory name\n",argv[0]);
exit(1);
}
sprintf(fifoname, "fifo_%d", getpid());
if (strcmp(argv[1], "0"))
if (mkfifo(fifoname, S_IFIFO | 0666) < 0) { /*Creating own FIFO file for result*/
perror("Failed creating own clientfifo");
printf("Client error: Failed creating fifo_%d file\n", getpid());
exit(2);
}
if ((f = open(FIFONAME, O_WRONLY)) < 0) { /*Opening serverfifo for writing*/
perror("Failed connecting to server");
exit(3);
}
strcpy(msg.dir, argv[1]);
strcpy(msg.spec, argv[2]);
msg.pid = getpid();
write(f, &msg, sizeof(msg));
if (strcmp(argv[1], "exit")) { /* The client is not expecting any result
because the server stopped*/
if ((fc = open(fifoname, O_RDONLY)) < 0) { /*Opening own fifo for reading*/
perror("Failed opening own fifo");
printf("Client error: Failed opening own %s file\n", fifoname);
exit(4);
}
read(fc, &msg, sizeof(msg));
printf("Client %d, received: %s%s\n", getpid(), msg.dir, msg.spec);
close(fc);
}
unlink(fifoname);
close(f);
exit(0);
}
公共头文件:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#define FIFONAME "server_fifo"
#define MAXLEN 1000
typedef struct {
int pid; /*folyamat azonositoja*/
char dir[MAXLEN];
char spec[MAXLEN];
} Message;
我得到的输出是:
-bash-4.1$ ./client dir -d
Client 42723, received: 16K,2 directories, 2 files
a
虽然看起来应该像这样:
-bash-4.1$ ./client dir -d
Client 42723, received: 16K,2 directories, 2 files
a
b
dir1
dir2
为了获得完整的输出需要修改什么?
问题出在server.c内部的第52行。您正在使用fgets()
将输出复制到msg.spec
。但是fgets()
停止接受换行符('\ n')的输入。因此,您只会看到一个结果。
要克服这一点,您可以执行以下操作:
char str[100]; // arbitrary length
while(fgets(str, MAXLEN, g))
{
strcat(msg.spec, str);
}
这会在每次迭代时不断获取输入并将每一行连接到先前的输出。