C中的基本共享内存程序
Posted
技术标签:
【中文标题】C中的基本共享内存程序【英文标题】:Basic shared memory program in C 【发布时间】: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 等粘贴箱)。 请告诉我们当您尝试运行我们的代码时发生了什么。 【参考方案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;
【讨论】:
以上是关于C中的基本共享内存程序的主要内容,如果未能解决你的问题,请参考以下文章