2014-09-07 1 views
0

У меня есть сервер и два разных клиента. Сервер и клиенты свяжутся между ними через FIFO. Каждый клиент сначала отправляет серверу переменную struct, которая содержит clientpid и число. Номер служит для различения клиента. Затем сервер делает adobeate fifo для каждого клиента. После этого сервер отправляет отдельное сообщение каждому клиенту. Когда я запускаю сервер и клиенты, клиент не получает сообщение, они зависают при чтении. Почему это происходит и что мне делать, чтобы исправить это? (В этом примере я упростил клиентов, они почти одинаковы, за исключением числа, которое они передают на сервер, чтобы отличить себя. В исходной программе два клиента будут делать разные вещи, и они получат разные данные от сервера, поэтому мне нужно различать их.)Отправка сообщения подтверждения серверу через fifo, чтобы отличать клиентов, клиенты не получают после сообщений

server.c

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <assert.h> 
#include <unistd.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/wait.h> 
#include <sys/un.h> 
#include <stdint.h> 
#include <sys/time.h> 
#include <arpa/inet.h> 
#include <fcntl.h> 


#define ec_neg1(s,m) if((s) == -1) {perror(m); exit(errno);} 

#define SERVER_FIFO_NAME "fifo_server" 
#define PERM_FILE  0664 

struct acknow_ 
{ 
pid_t clientpid; 
int num; 
}; 


int make_fifo_name(pid_t pid, char *name, size_t name_max) 
{ 
snprintf(name, name_max, "fifo%ld", (long)pid); 
return 0; 
} 


int main() 
{ 
int fd_server; 
int fd_send; 
int fd_recv; 
ssize_t nread; 
struct acknow_ acknow; 

char fifo_send[100]; 
char fifo_recv[100]; 

char msg1[100] = "SENDER GOT THE MESSAGE\n"; 
char msg2[100] = "RECEIVER GOT THE MESSAGE\n"; 

printf("server is started\n"); 

if(mkfifo(SERVER_FIFO_NAME, PERM_FILE) == -1 && errno != EEXIST) 
    {perror("can't make fifo"); exit(errno); } 

    ec_neg1(fd_server = open(SERVER_FIFO_NAME, O_RDWR), "cant open fd_server") 

    while(1) 
    { 
    ec_neg1(nread = read(fd_server, &acknow, sizeof(acknow)), "can't read from fd_server") 
    if (nread == 0) 
    { 
     errno = ENETDOWN; 
     perror("nread == 0"); exit(errno); 
    } 

    if(acknow.num == 1) /* sender's pid arrived first */ 
    { 

     /*MAKE FIFO OF THE SENDER*/ 
     make_fifo_name(acknow.clientpid, fifo_send, sizeof(fifo_send)); 

     ec_neg1(fd_send = open(fifo_send, O_WRONLY), "can't open fifo_send") 

     /*GET PID OF THE RECEIVER*/ 
     ec_neg1(nread = read(fd_server, &acknow, sizeof(acknow)), "can't read from fd_server") 

     if (nread == 0) 
     { 
     errno = ENETDOWN; 
     perror("nread == 0"); exit(errno); 
     } 


     /*MAKE FIFO OF THE RECEIVER*/ 
     make_fifo_name(acknow.clientpid, fifo_recv, sizeof(fifo_recv)); 

     ec_neg1(fd_recv = open(fifo_recv, O_WRONLY), "can't open fifo_recv") 

    } 
    else /* receiver's pid arrived first */ 
    { 

     /*MAKE FIFO OF THE SENDER*/ 
     make_fifo_name(acknow.clientpid, fifo_recv, sizeof(fifo_recv)); 

     ec_neg1(fd_recv = open(fifo_recv, O_WRONLY), "can't open fifo_recv") 

     /*GET PID OF THE RECEIVER*/ 
     ec_neg1(nread = read(fd_server, &acknow, sizeof(acknow)), "can't read from fd_server") 

     if (nread == 0) 
     { 
     errno = ENETDOWN; 
     perror("nread == 0"); exit(errno); 
     } 

     /*MAKE FIFO OF THE RECEIVER*/ 
     make_fifo_name(acknow.clientpid, fifo_send, sizeof(fifo_send)); 

     ec_neg1(fd_send = open(fifo_send, O_WRONLY), "can't open fifo_name") 


    } 

    printf("sending message to sender\n"); 
    ec_neg1(write(fd_send, &msg1, sizeof(msg1)), "can't write to fd_send") 
    printf("sending message to receiver\n"); 
    ec_neg1(write(fd_recv, &msg2, sizeof(msg2)), "can't write to fd_recv") 

    ec_neg1(close(fd_send), "can't close fd_send") 
    ec_neg1(close(fd_recv), "can't close fd_recv") 

    printf("done\n"); 
} 

    ec_neg1(close(fd_server), "can't close fd_server") 



return 0; 
} 

Client1.c (здесь я отправляю только client1, Client2 просто тот же самый код, просто измените «acknow.num» на «2», если вы хотите их запустить.)

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <assert.h> 
#include <unistd.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/wait.h> 
#include <sys/un.h> 
#include <stdint.h> 
#include <sys/time.h> 
#include <arpa/inet.h> 
#include <fcntl.h> 



#define ec_neg1(s,m) if((s) == -1) {perror(m); exit(errno);} 

#define SERVER_FIFO_NAME "fifo_server" 
#define PERM_FILE  0664 


struct acknow_ 
{ 
pid_t clientpid; 
int num; 
}; 


int make_fifo_name(pid_t pid, char *name, size_t name_max) 
{ 
snprintf(name, name_max, "fifo%ld", (long)pid); 
return 0; 
} 


int main() 
{ 

int fd_server, fd_client; 
ssize_t nread; 
char fifo_name[100]; 
char msg[100]; 
struct acknow_ acknow; 


printf("client1 started\n"); 

acknow.clientpid = getpid(); 
acknow.num = 1; 


make_fifo_name(acknow.clientpid, fifo_name, sizeof(fifo_name)); 

if (mkfifo(fifo_name, PERM_FILE) == -1 && errno != EEXIST) 
    {perror("can't make fifo"); exit(errno); } 

ec_neg1(fd_server = open(SERVER_FIFO_NAME, O_WRONLY), "can't open fd_server") 

ec_neg1(write(fd_server, &acknow, sizeof(acknow)),"can't write to fd_server") 

ec_neg1(fd_client = open(fifo_name, O_RDWR), "can't open fifo_name" ) 


while((nread = read(0, &msg, sizeof(msg)))) 
{ 

    write(1, msg, nread); 

} 

if (nread == 0) 
{ 
    errno = ENETDOWN; 
    perror("nread == 0"); exit(errno); 
} 
if (nread == -1) 
perror("can't read"); exit(errno); 



ec_neg1(close(fd_server), "can't close fd_server") 
ec_neg1(close(fd_client), "can't close fd_client") 
ec_neg1(unlink(fifo_name), "can't unlink fifo_name") 


return 0; 
} 
+0

Вы говорите: «Тогда сервер делает adeguate fifo для каждого клиента». Я не думаю, что это правда. Сервер делает только один FIFO. Клиенты, как представляется, создают свои собственные FIFO. – abligh

+0

@abligh, да, вы правы, это открывает филосы клиентов, я просто выразил это неправильно. – user3717434

+0

решено! это не работает только потому, что в клиенте я читаю из stdin вместо трубы! извините, это была глупая ошибка. – user3717434

ответ

0

Во-первых, на сервере вы открываете считываемый FIFO O_WRONLY. Это должно быть O_RDONLY.

Во-вторых, на клиенте вы открываете считываемый FIFO O_RDWR. Я считаю, что это неопределенное поведение в POSIX (вы не упоминаете ОС) и должно быть O_RDONLY. Этого достаточно, чтобы продолжать.

+0

Я думаю, вы ошибаетесь. Сервер записывает в fifo клиента, а не читает его. Клиент записывает на сервер fifo. НЕПРАВИЛЬНО. RDWR не является стандартом, но поскольку я на Linux, и возможности для него не являются проблемой для этого примера, все в порядке. Он служит для блокировки чтения его fifo, пока что-то там не написано сервером (вы можете проверить его в книге «Расширенное программирование UNIX»). В любом случае, я также попробовал, как вы сказали, и это дает мне ошибку «плохое описание файла» для fd_server. С моей версией она не дает никаких ошибок. – user3717434

 Смежные вопросы

  • Нет связанных вопросов^_^