【问题标题】:Basic shared memory program in CC中的基本共享内存程序
【发布时间】:2010-05-11 11:49:15
【问题描述】:

我想使用共享内存在 C 语言中制作一个基本的聊天应用程序。我在 Linux 中工作。应用程序在于写客户端和服务器可以读取,如果服务器写入客户端可以读取消息。

我尝试这样做,但我无法实现客户端和服务器之间的通信。代码如下:

服务器.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;
 }

客户端.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;
 }

共享内存模块如下:

#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);
}

【问题讨论】:

  • 请正确格式化您的代码(或将其上传到 privatepaste 等粘贴箱)。
  • 请告诉我们当您尝试运行我们的代码时发生了什么。

标签: c shared-memory


【解决方案1】:

等到您可以正常工作时,您将重新发明管道。套接字是更好的解决方案,它还涵盖了服务器和客户端不在同一台机器上运行的更常见的场景。

【讨论】:

    【解决方案2】:
    /* 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;
    }
    

    【讨论】:

      【解决方案3】:
      /* 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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-29
        • 2012-03-28
        • 1970-01-01
        • 1970-01-01
        • 2013-05-09
        • 2015-07-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多