Question

I have a sample code for server and client.But when i run client with fist input data then sever is not detecting that when i run the client second then server prints first input data.please some body explain me this behavior of my code.

1.Sever.c

#include"share.h"
main()
{
    int ret=0;
    int shmid=0;
    void *shmaddr=0;
    int running=1;
    shm_buf *shmstruct=NULL;
    shmid=shminit();
    if(ret== EXIT_FAILURE)
        return;
    if((shmaddr=shmattach(shmid)) == NULL)
        return;
    shmstruct=(shm_buf*)shmaddr;
    while(running)
    {
        if( shmstruct->flag ==0)
        {
            printf("waiting for client......\n");
        }
        else
        {
            printf("%s\n", shmstruct->buffer);
            if(strncmp(shmstruct->buffer,"end",3)==0)
            {
                break;
            }
            shmstruct->flag=0;
        }
        sleep(2);
    }
    ret=shmdetach(shmaddr);

    if(ret== EXIT_FAILURE)
        return;

    ret=shmdel(shmid);
    if(ret== EXIT_FAILURE)
        return;

}

2.client.c

#include"share.h"
main()
{
    int ret=0;
    int shmid=0;
    void *shmaddr=0;
    shm_buf *shmstruct=NULL;
    shmid=shminit();
    if(ret== EXIT_FAILURE)
        return;
    if((shmaddr=shmattach(shmid)) == NULL)
        return;
    shmstruct=(shm_buf*)shmaddr;
    if( shmstruct->flag ==0)
    {
        shmstruct->flag=1;
        printf("Enter meeeage:");
        fgets( shmstruct->buffer,sizeof(shm_buf),stdin);
    }
}

3.share.h

#include<stdio.h>
#include<string.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<error.h>
#include<errno.h>
#define EXIT_FAILURE -1
#define EXIT_SUCCESS 0
#define TRUE 1
#define FALSE 0
struct share
{
    int flag;
    char buffer[BUFSIZ];
};
typedef struct share shm_buf;
int shminit()
{
    int shmid=0;
    key_t key=ftok("/home/rajdhar/sample/shm/share.h",'A');
    if(key<0)
    {
        printf("ftok failed:%s\n",strerror(errno));
        return EXIT_FAILURE;
    }
    printf("key has been created successfuuly\n");

    shmid=shmget(key,sizeof(shm_buf),IPC_CREAT|0666);
    if(shmid<0)
    {
        printf("shmget failed:%s\n",strerror(errno));
        return EXIT_FAILURE;
    }
    printf("%d share memory has been created successfully\n",shmid);
    return shmid;
}

void *shmattach(int shmid)
{
    void *shmaddr=NULL;
    shmaddr=shmat(shmid,(void *)0,0);
    if(shmaddr == NULL)
    {
        printf("shmat failed:%s\n",strerror(errno));
        return NULL;
    }
    printf("memory has been attached with process successfulyy\n");
    return shmaddr;
}

int shmdetach(void *shmaddr)
{
    int ret = FALSE;
    ret=shmdt(shmaddr);
    if(ret<0)
    {   
        printf("shmdt failed:%s\n",strerror(errno));
        return EXIT_FAILURE;
    }
    printf("share memory has been detached successfully\n");
    return EXIT_SUCCESS;
}

int shmdel(int shmid)
{
    int ret = FALSE;
    ret=shmctl(shmid,IPC_RMID,0);
    if(ret<0)
    {
        printf("shmdt failed:%s\n",strerror(errno));
        return EXIT_FAILURE;
    }
    printf("Share memory has been deleted properly\n");
    return TRUE;
}

Example:- 1->./server 2->./client enter message:hello world server will not print any thing. 3-> ./client enter message:i am in the world. server prints "hello world"

Was it helpful?

Solution

In the client you have this:

shmstruct->flag=1;
printf("Enter meeeage:");
fgets( shmstruct->buffer,sizeof(shm_buf),stdin);

Which notifies the server before the data has been read into shmstruct->buffer.

You should probably set shmstruct->flag to 1 only when it has read the data into shmstruct->buffer:

printf("Enter meeeage:");
fgets( shmstruct->buffer,sizeof(shm_buf),stdin);
shmstruct->flag=1;

In production code you may like to use process shared mutex and condition variable to protect your shared state from corruption and notify the waiting process that the state has changed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top