Правильное соединение клиент-сервер FIFO
Я пытаюсь писать простые клиентские и серверные программы C, общаясь друг с другом в отдельных терминалах.
сервер должен создать общедоступный fifo и дождаться клиента. Между тем клиент создает свой собственный fifo, через который придет ответ сервера. Задача клиента-отправить серверу имя, созданное очередью, и получить взамен результат .
Я искал ответ, например: fifo-сервер-программа, пример-из-через-имени-труб-в-линукс-Баш, how-to-send-a-simple-string-between-two-programs-using-pipes. Я начал с кода из третьей ссылки и медленно изменил его.
Теперь у меня есть клиент, принимающий ввод от пользователя, отправляющий его на сервер и получающий его обратно. Но это работает только один раз. Понятия не имею почему. Тело основной функции ниже. Буду благодарен за любую помощь.
EDIT: Я получил это работает! : D коды ниже, возможно, это поможет кому-то.
сервер.код 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: %sn",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;
}
клиент.код 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: %sn",tab);
close(fds[0]);
close(fds[1]);
unlink(myfifo2);
return 0;
}
2 ответов
почему бы вам просто не управлять обоими fifo на сервере? Простое изменение кода для этого делает его работу правильной.
Если вы действительно хотите иметь отношения клиент-сервер, с сервером, обслуживающим много разных клиентов, сокеты, вероятно, будут лучшим выбором.
клиент.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;
}
сервер.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;
}
он работает только один раз из-за того, как работают именованные каналы. Каждый раз, когда вы open
именованный канал для чтения блокируется до тех пор, пока другой процесс не откроет его для записи. Затем вы соединяетесь, и файловый дескриптор соединяет ваши процессы. Как только любой конец закрывает это соединение, это конец этой трубы. Для того, чтобы ваш сервер "принял другое соединение", ему необходимо переместить open
и close
труб в свой основной контур поэтому его можно спарить вверх по снова и снова.