具有共享内存和文件作为数据库的 IPC V 客户端/服务器应用程序,用 C 编写
Posted
技术标签:
【中文标题】具有共享内存和文件作为数据库的 IPC V 客户端/服务器应用程序,用 C 编写【英文标题】:IPC V client/server application with shared memory and a file as database, written on C 【发布时间】:2017-10-26 11:54:14 【问题描述】:我仍然无法解决这个问题...我有一个使用共享内存作为通信方式的客户端/服务器应用程序的实现。但是,我正在尝试使用一个本地文件作为服务器端的数据库。我猜它是这样的: - 当 客户端 需要某些东西时,他会向 服务器 发出请求(比如说,“如果数据库中有 John,请打印我 John 的名字”。 服务器然后搜索数据库并返回John的字符序列,显然他的客户端编号为123456789,然后客户端打印它。真正的问题发生在客户端尝试阅读此内容 - 我无法理解他必须如何从服务器获取信息并随意使用它。
目前我正在使用临时文件作为数据库,但我什至无法使用它。当客户端尝试从数据库读取时,我得到 Segmentation fault。我真的很想了解如何将本地文件读取到服务器并将其用作数据库,然后在客户端开始发出请求并因此将数据传递给客户端时使用该数据库。
任何帮助将不胜感激..
定义:
#define SERVER_BUSY 0
#define SERVER_READY 1
#define DATA_CONSUMED 2
#define REQUEST 3
#define BUSY 4
#define SEARCH 0
#define GETALL 1
#define INSERT 2
#define MAX 100
struct SharedMemory
int requestType;
int processId;
int status;
char names[1];
int fakNums[1];
int count;
;
这是我的服务器实现:
void main(int argc, char *argv[])
key_t sharedMemoryKey;
int sharedMemoryId;
struct SharedMemory *sharedMemoryPointer;
sharedMemoryKey = ftok(".", 'x');
sharedMemoryId = shmget(sharedMemoryKey, sizeof(struct SharedMemory), IPC_CREAT | 0666);
if (sharedMemoryId < 0)
printf("SERVER ERROR\n");
exit(1);
sharedMemoryPointer = (struct SharedMemory *) shmat(sharedMemoryId, NULL, 0);
if ((int) sharedMemoryPointer == -1)
printf("SHARED MEMERY ERROR\n");
exit(1);
printf("ATTACHED TO SHARED MEMORY...\n");
printf("START CLIENT...\n");
//temp data
int totalCount = 1;
struct SharedMemory sharedMem;
for (int i = 0; i < totalCount; i++)
sharedMem.names[i] = "NAME";
sharedMem.fakNums[i] = i;
//-temp data
sharedMemoryPointer->status = SERVER_READY;
while (1)
if (sharedMemoryPointer->status != REQUEST)
sleep(1);
else
printf("START WORKING...\n");
sharedMemoryPointer->status = SERVER_BUSY;
int requestType = sharedMemoryPointer->requestType;
switch (requestType)
case SEARCH :
int pos = 0;
for (int i = 0; i < totalCount; i++)
if (strcmp(sharedMem.names[i], sharedMemoryPointer->names[0]) == 0)
strcpy(sharedMemoryPointer->names[pos], sharedMem.names[i]);
sharedMemoryPointer->fakNums[pos] = sharedMem.fakNums[i];
pos++;
break;
sharedMemoryPointer->count = pos;
break;
case GETALL :
for (int i = 0; i < totalCount; i++)
strcpy(sharedMemoryPointer->names[i], sharedMem.names[i]);
sharedMemoryPointer->fakNums[i] = sharedMem.fakNums[i];
sharedMemoryPointer->count = totalCount;
break;
case INSERT :
strcpy(sharedMem.names[totalCount], sharedMemoryPointer->names[0]);
sharedMem.fakNums[totalCount] = sharedMemoryPointer->fakNums[0];
totalCount;
break;
int clientPid = sharedMemoryPointer->processId;
printf("WAKE UP THE PROCESS...\n");
kill(clientPid, SIGCONT);
sharedMemoryPointer->status = SERVER_READY;
这是我的客户端实现:
void onServerReady();
key_t sharedMemoryKey;
int sharedMemoryId;
struct SharedMemory *sharedMemoryPointer;
bool isSearching = false;
bool isInserting = false;
bool isFetchingAll = false;
void main(int argc, char *argv[])
//init
char* SEARCHARG = "-s";
char* INSERTARG = "-i";
char* LISTARG = "-l";
sharedMemoryKey = ftok(".", 'x');
sharedMemoryId = shmget(sharedMemoryKey, sizeof(struct SharedMemory), 0666);
if (sharedMemoryId < 0)
printf("SHARED MEMORY ERROR\n");
exit(1);
sharedMemoryPointer = (struct SharedMemory *) shmat(sharedMemoryId, NULL, 0);
if ((int) sharedMemoryPointer == -1)
printf("*** shmat error (client) ***\n");
exit(1);
printf(" CLIENT ATTACHED TO SHARED MEMORY\n");
signal(SIGCONT, onServerReady);
//set our request
if (argc < 2)
printf(" NO ARGS. EXITING\n");
exit(1);
if (strcmp(argv[1], SEARCHARG) == 0)
isSearching = true;
if (argc < 3)
printf(" NOT ENOUGH ARGS. EXITING\n");
exit(1);
while (sharedMemoryPointer->status != SERVER_READY)
sleep(1);
sharedMemoryPointer->status = BUSY;
sharedMemoryPointer->processId = getpid();
sharedMemoryPointer->requestType = SEARCH;
strcpy(sharedMemoryPointer->names[0], argv[2]);
sharedMemoryPointer->status = REQUEST;
else if (strcmp(argv[1], LISTARG) == 0)
isFetchingAll = true;
while (sharedMemoryPointer->status != SERVER_READY)
sleep(1);
sharedMemoryPointer->status = BUSY;
sharedMemoryPointer->processId = getpid();
sharedMemoryPointer->requestType = GETALL;
sharedMemoryPointer->status = REQUEST;
else if (strcmp(argv[1], INSERTARG) == 0)
isInserting = true;
if (argc < 4)
printf(" NOT ENOUGH ARGS. EXITING\n");
exit(1);
while (sharedMemoryPointer->status != SERVER_READY)
sleep(1);
sharedMemoryPointer->status = BUSY;
sharedMemoryPointer->processId = getpid();
sharedMemoryPointer->requestType = INSERT;
strcpy(sharedMemoryPointer->names[0], argv[2]);
sharedMemoryPointer->fakNums[0] = atoi(argv[3]);
sharedMemoryPointer->status = REQUEST;
//wait
pause();
//while (sharedMemoryPointer->status != FILLED)
// ;
// printf(" Client found the data is ready...\n");
//printf(" Client found %d %d %d %d in shared memory...\n",
// sharedMemoryPointer->data[0], sharedMemoryPointer->data[1],
// sharedMemoryPointer->data[2], sharedMemoryPointer->data[3]);
// sharedMemoryPointer->status = TAKEN;
// printf(" Client has informed server data have been taken...\n");
// shmdt((void *) sharedMemoryPointer);
// printf(" Client has detached its shared memory...\n");
// printf(" Client exits...\n");
// exit(0);
void onServerReady()
if (isFetchingAll || isSearching)
int count = sharedMemoryPointer->count;
printf("\n %d", count);
//for (int i = 0; i < count; i++)
// printf("Name %s, fakNum %d \n", sharedMemoryPointer->names[i], sharedMemoryPointer->fakNums[i]);
//
else
printf("\nSuccessfull insertion!");
【问题讨论】:
除了 gpeche 在他的有用答案中解决的问题之外,这对于 sysv shm 来说听起来并不是一件好事。您应该使用面向消息的东西,系统 v 消息队列,或者甚至更好的 unix 域套接字、udp 等 【参考方案1】:我的 C 有点生疏了,但看起来你的 SharedMemory
结构(位于 SysV 共享内存中)正在加载指向非共享内存中的 Data
的指针(通过 malloc
分配,或者静态地在进程的私有内存空间内)这在另一边是行不通的,因为:
您应该使用shmget
分配一个足够大的内存块以容纳您想要共享的所有内容,然后将所有信息放入该块中。避免使用指针,将信息嵌入到您的共享内存结构中。
【讨论】:
感谢您的帮助!但是,当我尝试将信息嵌入到我的结构SharedMemory char names[20]
中时,shmget() 方法不起作用。你知道为什么会这样吗?
我已经更新了我的代码。你能指导我如何制作学生信息数组(姓名和数字作为字符串)并从文件中加载它们吗?
@Calihog 您应该将您的结构定义添加到问题中,如果不知道这些,很难知道发生了什么。
是的,抱歉。我已经在上面的帖子中添加了定义!以上是关于具有共享内存和文件作为数据库的 IPC V 客户端/服务器应用程序,用 C 编写的主要内容,如果未能解决你的问题,请参考以下文章