简体   繁体   中英

Basic shared memory program in C

I want to make a basic chat application in C using Shared memory. I am working in Linux. The application consist in writing the client and the server can read, and if the server write the client can read the message.

I tried to do this, but I can't achieve the communication between client and server. The code is the following:

Server.c

int
main(int argc, char **argv)
{
 char *msg;
 static char buf[SIZE];
 int n;

 msg = getmem();
 memset(msg, 0, SIZE);
 initmutex();

 while ( true )
 {
  if( (n = read(0, buf, sizeof buf)) > 0 )
  {
   enter();
   sprintf(msg, "%.*s", n, buf);
   printf("Servidor escribe: %s", msg);
   leave();
  }else{
   enter();
   if ( strcmp(buf, msg) )
   {
    printf("Servidor lee: %s", msg);
    strcpy(buf, msg);
   }
   leave();
   sleep(1);
  }
 }
 return 0;
 }

Client.c

int
main(int argc, char **argv)
{
 char *msg;
 static char buf[SIZE-1];
 int n;

 msg = getmem();
 initmutex();

 while(true)
 {
  if ( (n = read(0, buf, sizeof buf)) > 0 )
  {
   enter();
   sprintf(msg, "%.*s", n, buf);
   printf("Cliente escribe: %s", msg);
   leave();
  }else{
   enter();
   if ( strcmp(buf, msg) )
   {
    printf("Cliente lee: %s", msg);
    strcpy(buf, msg);
   }
   leave();
   sleep(1);
  }
 }
 printf("Cliente termina\n");
 return 0;
 }

The shared memory module is the folowing:

#include "common.h"

void
fatal(char *s)
{
 perror(s);
 exit(1);
}

char *
getmem(void)
{
 int fd;
 char *mem;

 if ( (fd = shm_open("/message", O_RDWR|O_CREAT, 0666)) == -1 )
  fatal("sh_open");
 ftruncate(fd, SIZE);
 if ( !(mem = mmap(NULL, SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) )
  fatal("mmap");
 close(fd);
 return mem;
}

static sem_t *sd;

void
initmutex(void)
{
 if ( !(sd = sem_open("/mutex", O_RDWR|O_CREAT, 0666, 1)) )
  fatal("sem_open");
}

void
enter(void)
{
 sem_wait(sd);
}

void
leave(void)
{
 sem_post(sd);
}

By the time you'll have this working right, you'll have re-invented a pipe. A socket is the better solution, that will also cover the more common scenario where the server and the client are not running on the same machine.

/* client */
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

#define SIZEOFSHMSEG 50         /* Size of the shared mem segment    */

#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include<fcntl.h>
#define PORT        6002

int main()
{ char buffer[512];
     int rc, shmid, i,l,choice,n;
     void *shm_address;
     struct shmid_ds shmid_struct;
 char c,ch;
     char HOST[30];
 char hostname[100];
 int sd;
 struct sockaddr_in sin;
 struct sockaddr_in pin;
 struct hostent *hp;

 printf("enter the server's ip address:");
 scanf("%s",HOST);
 n=strlen(HOST);
 HOST[n]='\0';


 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
                perror("socket");
                exit(1);
        }

 /* fill in the socket structure with host information */
 memset(&pin, 0, sizeof(pin));
 pin.sin_family = AF_INET;
 pin.sin_addr.s_addr = inet_addr(HOST);
 pin.sin_port = htons(PORT);


 /* connect to PORT on HOST */
 if (connect(sd,(struct sockaddr *)  &pin, sizeof(pin)) == -1) {
  perror("connect");
  exit(1);
 }

  /* shared memory setup */
     shmid = shmget(2222, SIZEOFSHMSEG, 0666 | IPC_CREAT | IPC_EXCL);
     if (shmid == -1)
       {
         printf("main: shmget() failed\n");
         return -1;
       }

     /* Attach the shared memory segment to the server process.       */
     shm_address = shmat(shmid, NULL, 0);
     if ( shm_address==NULL )
       {
         printf("main: shmat() failed\n");
         return -1;
       }
 fcntl(sd, F_SETFL, O_NONBLOCK); 
 buffer[0]='\0';
 strcpy((char *)shm_address,buffer); 
 for(;;)
 { 
  printf("----------------------------------------------------------\n");
  printf("1.read from shared mem\n2.write to shared area\n3.exit\n");
  printf("ur choice:");
  scanf("%d",&choice);

  n = read(sd, buffer, 512);
  buffer[n] = '\0';
  strcpy((char *) shm_address, buffer);   

   if(choice==1)
   { strcpy(buffer,(char *)shm_address);
    printf("display:%s\n",buffer);
   }

   if(choice==2)
   { printf("enter the data:");

    scanf(" %[^\n]",buffer);
    n=strlen(buffer);
    buffer[n]='\0';
    strcpy((char *) shm_address, buffer);
    write(sd, buffer, strlen(buffer));
   }

   if(choice==3)
                        { printf("terminated\n");
    break;
   }
  printf("----------------------------------------------------------\n");
 }
 close(sd);
 rc = shmdt(shm_address);
     if (rc==-1)
       {
         printf("main: shmdt() failed\n");
         return -1;
       }
     rc = shmctl(shmid, IPC_RMID, &shmid_struct);
     if (rc==-1)
       {
         printf("main: shmctl() failed\n");
         return -1;
       }
 return 0;
}
/* server */
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define SIZEOFSHMSEG 50         /* Size of the shared mem segment    */

#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#include<fcntl.h>
#define PORT   6002

int main()
{ char buffer[512];
     int rc, shmid, i,l,choice,n;
     void * shm_address;
     struct shmid_ds shmid_struct;
 char c;

 int   sd, sd_current, cc;
 int   addrlen;
 struct   sockaddr_in sin;
 struct   sockaddr_in pin;

 /* get an internet domain socket */
 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  perror("socket");
  exit(1);
 }

 /* complete the socket structure */
 memset(&sin, 0, sizeof(sin));
 sin.sin_family = AF_INET;
 sin.sin_addr.s_addr = htonl(INADDR_ANY);
 sin.sin_port = htons(PORT);

 /* bind the socket to the port number */
 if (bind(sd, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
  perror("bind");
  exit(1);
 }

 /* show that we are willing to listen */
 if (listen(sd, 5) == -1) {
  perror("listen");
  exit(1);
 }

printf("waiting for client....\n");

 addrlen = sizeof(pin); 
 if ((sd_current = accept(sd, (struct sockaddr *)  &pin, &addrlen)) == -1) {
  perror("accept");
  exit(1);
 }
printf("connected..\n");

 /* shared memory setup */
     shmid = shmget(1111, SIZEOFSHMSEG, 0666 | IPC_CREAT | IPC_EXCL);
     if (shmid == -1)
       {
         printf("main: shmget() failed\n");
         return -1;
       }

     /* Attach the shared memory segment to the server process.       */
     shm_address = shmat(shmid, NULL, 0);
     if ( shm_address==NULL )
       {
         printf("main: shmat() failed\n");
         return -1;
       }
buffer[0]='\0';
strcpy((char *)shm_address,buffer);

fcntl(sd_current, F_SETFL, O_NONBLOCK); 
 for(;;)
 { 

  printf("----------------------------------------------------------\n");
  printf("1.read from shared mem\n2.write to shared area\n3.exit\n");
  printf("ur choice:");
  scanf("%d",&choice);

  n=read(sd_current, buffer, 512);
  buffer[n] = '\0';
  strcpy((char *) shm_address, buffer);

   if(choice==1)
   { strcpy(buffer,(char *)shm_address);
    printf("display:%s\n",buffer);
   }

   if(choice==2)
   { printf("enter the data:");
    scanf(" %[^\n]",buffer);
    n=strlen(buffer);
    buffer[n]='\0';

    strcpy((char *) shm_address, buffer);
    write(sd_current, buffer, strlen(buffer));
   }
   if(choice==3)
                        { printf("terminated\n");
    break;
   }
  printf("----------------------------------------------------------\n");
 }
 close(sd_current);
 close(sd);
 rc = shmdt(shm_address);
     if (rc==-1)
       {
         printf("main: shmdt() failed\n");
         return -1;
       }
     rc = shmctl(shmid, IPC_RMID, &shmid_struct);
     if (rc==-1)
       {
         printf("main: shmctl() failed\n");
         return -1;
       }
 return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM