#c #linux #named-pipes
#c #linux #именованные каналы
Вопрос:
Здравствуйте, я пытаюсь создать программу на c, которая использует именованные каналы для связи с другой программой, но если я запускаю ее более одного раза, большую часть времени она терпит неудачу, иногда работая отлично, хотя я ничего не меняю между тестами. Вот код для arbitro.c программа, которую я выполняю первой
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
int main(int argc, char *argv[])
{
int fd,id1,cont_pront=0,i=0;
char nomejog[40]="",instrucao[40]="";
// FIFO file path
char * myfifo = "myfifo";
// Creating the named file(FIFO)
mkfifo(myfifo, 0666);
do{
fd = open(myfifo,O_RDONLY);
if(fd == -1){
fprintf(stdout, "Erro a abrir.n");
}
// First open in read only and read
for(int i=0;i<2;i ){
read(fd, nomejog, 40); //Recebe o nome do jogador
read(fd, amp;id1,sizeof(id1)); //Recebe o id do primeiro jogador
fprintf(stdout, "Nome: %s -» %dn", nomejog,id1);
cont_pront ;
}
fprintf(stdout, "Nº: %dn", cont_pront);
//Now open in write mode and write
fd = open(myfifo,O_WRONLY);
if(fd == -1){
fprintf(stdout, "Erro a abrir.n");
}
if(cont_pront >= 2){
cont_pront = -1;
}
write(fd, amp;cont_pront, sizeof(int));
close(fd);
// optind is for the extra arguments
// which are not parsed
for(; optind < argc; optind ){
if(i == 0){
printf("Duração do campeonato: %sn", argv[optind]);
}else{
if(i == 1){
printf("Tempo de espera: %sn", argv[optind]);
}
}
i ;
}
}while(strcmp(instrucao,"exit") != 0);
return 0;
}
и вот код для cliente.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
int main(int argc, char *argv[]){
int fd1,cont_pront=0;
char nomejog[40]="";
// FIFO file path
char * myfifo = "myfifo";
// Creating the named file(FIFO)
mkfifo(myfifo, 0666);
// Open FIFO for write only
fd1 = open(myfifo, O_WRONLY);
//Enviar o nome do jogador ao arbitro
for(int i=0;i<2;i ){
write(fd1, nomejog,strlen(nomejog) 1); //Envia o nome do jogador já pronto
write(fd1,amp;i, sizeof(int)); //Envia o id
strcpy(nomejog,"pedro");
}
close(fd1);
//Receber quantos jogadores estão prontos
fd1 = open(myfifo, O_RDONLY);
read(fd1, amp;cont_pront, sizeof(int)); //Recebe o nome do jogador
if(cont_pront == -1){
//Tem jogadores necessários para começar o jogo
fprintf(stdout,"Existem jogadores suficientes, o campeonato vai ser iniciado...n");
execl("GAMEDIR/game01","GAMEDIR/game01", NULL);
}else{
//Ainda não tem jogadores suficientes para começar o jogo
fprintf(stdout,"Nao tem jogadores suficientes para comecar o campeonato.n");
}
close(fd1);
return 0;
}
если все идет хорошо, это должно говорить о том, что игроков достаточно, и игра выполняется, но по какой-то причине иногда все повторяется, отправляя больше игроков пустыми, или клиент останавливается на полпути выполнения или даже не отправляет правильных игроков в первую очередь
Комментарии:
1. Первое, что нужно сделать, это проверить возвращаемые значения всех ваших системных вызовов, и
perror()
если они завершаются неудачей. Это поможет сузить возможную причину сбоя и должно быть сделано в любом случае.2. Одна ошибка заключается в том, что клиент записывает переменное количество байтов для
nomejog
(1 в первый раз, 6 во второй раз), а затем 4 байта для целогоi
числа. Ядро не гарантирует, что отдельные записи будут разделены, поэтому, когда сервер пытается прочитать 40 байт, он может прочитать все 15 байт,nomejog
а затем оставшиеся чтения сообщат о конце файла (который вы не проверяете) и оставят их буферы неинициализированными. Вам нужно будет изменить свой протокол, чтобы клиент и сервер договорились о том, сколько байтов ожидается для отправки и получения для каждого фрагмента данных.