Obsługa kolejki komunikatów unix przy pomocy programu w C

0

Mam do przeanalizowania kod w C obsługujący kolejkę komunikatów w Linuxie, program klient który wysyła do serwera ciąg znaków, a serwer zmienia małe na duże liter. Nie rozumiem dlaczego gdy wyśle do serwera jedne znak po wywołaniu polecenia ipcs -q widzę 2 komunikaty czekające w kolejce przy MAX ustawionym na 2 to samo gdy ustawie MAX na 3 po wysłaniu 2 znaków widzę 2 komunikaty a powinien być jeden
o to kod klienta i serwera
KLIENT:

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>

#define MAX 2

typedef struct
{
	long typ;
	long pid;
	char tekst[MAX];
} komunikat;

int id_kolejki;
komunikat kom_odb, kom_wys;
//watek1
void* odbierz_komunikat()
{
	int x,c;
	while(1)
	{
		kom_odb.typ=getpid(); 
		memset(kom_odb.tekst, 0, MAX);
		x=msgrcv(id_kolejki, &kom_odb, sizeof(kom_odb)-sizeof(long),kom_odb.typ, 0);
		if(x==-1)
		{
			perror("Klient: Blad odebrania");
			exit(errno);
		} 
		printf("Klient %d odebral komunikat %s\n", getpid(), kom_odb.tekst); 
	}	
}

//watek2
void* wyslij_komunikat()
{
	int x,c;
	while(1)
	{
		kom_wys.typ=1;//odbiorca serwer 1
		kom_wys.pid=getpid();
	
		printf("Klient %d czeka na wprowadzenie tekstu: ", getpid());
		if((fgets(kom_wys.tekst, MAX, stdin))==NULL)
		{
			printf("Problem z czytaniem komunikatu\n");
			exit(1);
		}
		x=msgsnd(id_kolejki, &kom_wys, sizeof(kom_wys)-sizeof(long), 0);
		if(x==-1)
		{
			perror("Blad wysylania");
			exit(errno);
		}
		printf("Klient %d wyslal komunikat %s\n", getpid(), kom_wys.tekst);
	}
}

int main()
{
	int klucz,x;
	pthread_t tid1, tid2;
	klucz=ftok(".", 'A');
	if(klucz==-1)
	{
		perror("Klient: Blad tworzenia klucza");
		exit(errno);
	}
	id_kolejki=msgget(klucz, IPC_CREAT | 0600);
	if(id_kolejki==-1)
	{
		perror("Klient: Blad uzyskiwania dostepu do kolejki");
		exit(errno);
	}
	printf("Klient utworzyl/dolaczyl do kolejki %d\n", id_kolejki);
	//tworzenie
	if(pthread_create(&tid1, NULL, odbierz_komunikat, NULL))
	{
		perror("Klient: Blad tworzenia watku");
		exit(errno);
	}
	if(pthread_create(&tid2, NULL, wyslij_komunikat, NULL))
	{
		perror("Klient: Blad tworzenia watku");
		exit(errno);
	}
	//dolaczanie
	if(pthread_join(tid1, NULL))
	{
		perror("Klient: Blad dolaczenia watku");
		exit(errno);
	}
	if(pthread_join(tid2, NULL))
	{
		perror("Klient: Blad dolaczenia watku");
		exit(errno);
	}

	


	return 0;
}

SERWER:

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>

#define MAX 2

typedef struct
{
	long typ;
	long pid;
	char tekst[MAX];
} komunikat;
int id_kolejki;	
komunikat kom;
void obsluga(int sig);
int main()
{

	signal(SIGINT, obsluga);
	int klucz,x,i;
	klucz=ftok(".", 'A');
	if(klucz==-1)
	{
		perror("Blad tworzenia klucza");
		exit(errno);
	}
	id_kolejki=msgget(klucz, IPC_CREAT | 0600);
	if(id_kolejki==-1)
	{
		perror("Blad uzyskiwania dostepu do kolejki");
		exit(errno);
	}
	printf("Serwer utworzyl/dolaczyl do kolejki %d", id_kolejki);
	while(1)
	{
		kom.typ=1;
		x=msgrcv(id_kolejki, &kom, sizeof(kom)-sizeof(long), kom.typ, 0);
		if(x==-1)
		{
			perror("Blad odebrania");
			exit(errno);
		}
		printf("Serwer otrzymal komunikat %s od %d\n", kom.tekst, kom.pid);
		for(i=0; i<strlen(kom.tekst); i++)
		{
			kom.tekst[i] = toupper(kom.tekst[i]);
		}
		kom.typ = kom.pid;//odbiorca jest klient o pid
		x=msgsnd(id_kolejki, &kom, sizeof(kom)-sizeof(long), 0);
		if(x==-1)
		{
			perror("Blad wysylania");
			exit(errno);
		}
		printf("Serwer wyslal komunikat %s", kom.tekst);
	}

}

void obsluga(int sig)
{
	int klucz, x;
	klucz=ftok(".", 'A');
	if(klucz==-1)
	{
		perror("Blad ftok");
		exit(errno);
	}
	//uzyskaj dostep
	id_kolejki=msgget(klucz, IPC_CREAT|0600);
	if(id_kolejki==-1)
	{
		perror("Blad uzyskania dostepu");
		exit(errno);
	}
	x=msgctl(id_kolejki, IPC_RMID, 0);
	if(x==-1)
	{
		perror("Blad usuwania kolejki");
		exit(errno);
	}
	printf("Usunieto kolejke\n");
	exit(0);
}


0

Twoja pętla:

    while(1)
    {
        kom_wys.typ=1;//odbiorca serwer 1
        kom_wys.pid=getpid();

        printf("Klient %d czeka na wprowadzenie tekstu: ", getpid());
        if((fgets(kom_wys.tekst, MAX, stdin))==NULL)
        {
            printf("Problem z czytaniem komunikatu\n");
            exit(1);
        }
        x=msgsnd(id_kolejki, &kom_wys, sizeof(kom_wys)-sizeof(long), 0);
        if(x==-1)
        {
            perror("Blad wysylania");
            exit(errno);
        }
        printf("Klient %d wyslal komunikat %s\n", getpid(), kom_wys.tekst);
    }

Wysyła też białe znaki. Jeśli testujesz interaktywnie, to wpisanie [znak][enter] jest zapisane w buforze jako dwa znaki: [znak] oraz [\n], przez co klient wysyła do serwera 2 komunikaty.
Zwykłe wywołanie programu przez

echo -n "a" | ./client

będzie zachowywało się zgodnie z oczekiwaniem, tj. zapisze do kolejki tylko jeden komunikat.

1 użytkowników online, w tym zalogowanych: 0, gości: 1