Linux 正确的 FIFO 客户端-服务器连接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8611035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Proper FIFO client-server connection
提问by uluroki
I'm trying to write simple client and server C programs, communicating with each other in separate terminals.
我正在尝试编写简单的客户端和服务器 C 程序,在不同的终端中相互通信。
The server has to create a public fifo and wait for the client. Meanwhile the client is creating his own fifo through which the server's response will come. The task of the client is sending the server a name created by the queue and get in return the result of the ls
command.
服务器必须创建一个公共 fifo 并等待客户端。同时,客户端正在创建他自己的 fifo,服务器的响应将通过它来。客户端的任务是向服务器发送一个由队列创建的名称,并返回ls
命令的结果。
I did search for an answer, for example: fifo-server-program, example-of-using-named-pipes-in-linux-bash, how-to-send-a-simple-string-between-two-programs-using-pipes. I started with the code from the third link and slowly modified it.
我确实搜索了一个答案,例如:fifo-server-program,example-of-using-named-pipes-in-linux-bash,how-to-send-a-simple-string-between-two-programs-使用管道。我从第三个链接的代码开始,慢慢修改。
What I've got now, is a client taking input from the user, sending it to the server and receiving it back. But it only works once. I have no idea why. The body of main function is below. I will be grateful for any help.
我现在得到的是一个客户端从用户那里获取输入,将其发送到服务器并接收回来。但它只能工作一次。我不知道为什么。主要功能的主体如下。我将不胜感激任何帮助。
EDIT:I got it working! :D The codes are below, maybe it will help someone.
编辑:我让它工作了!:D 代码如下,也许它会帮助某人。
The server.c code:
server.c 代码:
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char* argv[])
{
int fds[2];
char tab[BUFSIZ];
int fd, n;
char *myfifo = "/tmp/serwer";
char *myfifo2 = "/tmp/client";
pipe(fds);
mkfifo(myfifo,0666);
while(1)
{
fds[0]=open(myfifo2,O_RDONLY);
fds[1]=open(myfifo,O_WRONLY);
read(fds[0],tab,BUFSIZ);
if (strcmp("klient",tab)==0) {
printf("Od klienta: %s\n",tab);
fd=open(tab,O_WRONLY);
if(fork()==0)
{
dup2(fds[1],1);
close(fds[1]);
execlp("ls","ls","-l",NULL);
close(fds[0]);
close(fds[1]);
}
else
{
dup2(fds[0],0);
n = read(fds[0],tab,BUFSIZ);
write(fd,tab,n);
close(fds[0]);
close(fds[1]);
}
}
memset(tab, 0, sizeof(tab));
close(fd);
close(fds[0]);
close(fds[1]);
}
unlink(myfifo);
return 0;
}
The client.c code:
client.c 代码:
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char* argv[])
{
int fds[2];
char *myfifo = "/tmp/serwer";
char *myfifo2 = "/tmp/client";
mkfifo(myfifo2,0666);
fds[0]=open(myfifo,O_RDONLY);
fds[1]=open(myfifo2,O_WRONLY);
char tab[BUFSIZ];
memset(tab, 0, sizeof(tab));
write(fds[1],"klient",6);
perror("Write:"); //Very crude error check
read(fds[0],tab,sizeof(tab));
perror("Read:"); // Very crude error check
printf("Odebrano od serwera: %s\n",tab);
close(fds[0]);
close(fds[1]);
unlink(myfifo2);
return 0;
}
采纳答案by Lalaland
Why don't you just manage both fifo's in the server? Simply changing your code to do this makes it work correctly.
你为什么不管理服务器中的两个先进先出?只需更改您的代码即可使其正常工作。
If you actually want to have a client-server relationship, with a server serving many different clients, sockets would probably be a better choice.
如果您确实想要建立客户端-服务器关系,并且服务器为许多不同的客户端提供服务,那么套接字可能是更好的选择。
client.cpp
客户端
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int client_to_server;
char *myfifo = "/tmp/client_to_server_fifo";
int server_to_client;
char *myfifo2 = "/tmp/server_to_client_fifo";
char str[BUFSIZ];
printf("Input message to serwer: ");
scanf("%s", str);
/* write str to the FIFO */
client_to_server = open(myfifo, O_WRONLY);
server_to_client = open(myfifo2, O_RDONLY);
write(client_to_server, str, sizeof(str));
perror("Write:"); //Very crude error check
read(server_to_client,str,sizeof(str));
perror("Read:"); // Very crude error check
printf("...received from the server: %s\n",str);
close(client_to_server);
close(server_to_client);
/* remove the FIFO */
return 0;
}
server.cpp
服务器.cpp
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
int main()
{
int client_to_server;
char *myfifo = "/tmp/client_to_server_fifo";
int server_to_client;
char *myfifo2 = "/tmp/server_to_client_fifo";
char buf[BUFSIZ];
/* create the FIFO (named pipe) */
mkfifo(myfifo, 0666);
mkfifo(myfifo2, 0666);
/* open, read, and display the message from the FIFO */
client_to_server = open(myfifo, O_RDONLY);
server_to_client = open(myfifo2, O_WRONLY);
printf("Server ON.\n");
while (1)
{
read(client_to_server, buf, BUFSIZ);
if (strcmp("exit",buf)==0)
{
printf("Server OFF.\n");
break;
}
else if (strcmp("",buf)!=0)
{
printf("Received: %s\n", buf);
printf("Sending back...\n");
write(server_to_client,buf,BUFSIZ);
}
/* clean buf from any data */
memset(buf, 0, sizeof(buf));
}
close(client_to_server);
close(server_to_client);
unlink(myfifo);
unlink(myfifo2);
return 0;
}
回答by Ben Hymanson
It only works once because of how named pipes work. Each time you open
a named pipe for read you block until another process opens it for write. Then you are paired up and the file descriptor connects your processes. Once either end closes that connection that's the end of that pipe. In order for your server to "accept another connection" it needs to move the open
and close
of the pipes into its main loop so it can be paired up over and over.
由于命名管道的工作方式,它只能工作一次。每次您open
使用命名管道进行读取时,您都会阻塞,直到另一个进程打开它进行写入。然后您配对并且文件描述符连接您的进程。一旦任一端关闭该连接,即为该管道的末端。为了让您的服务器“接受另一个连接”,它需要将管道的open
和移动close
到其主循环中,以便可以一遍又一遍地配对。