当前位置: 首页 > 知识库问答 >
问题:

用C语言编写共享内存和信号量的客户端服务器程序

谷梁驰
2023-03-14

我不太了解共享内存是如何工作的,我试图编写一个服务器-客户机程序,在该程序中,服务器和客户机使用共享内存和信号量相互通信

typedef struct shared_mem{
    int board[BOARD_SIZE * BOARD_SIZE];
    int goal;
    int client;
    int direction;
    sem_t sem_server;
}shared_mem;
shared_mem *msg;
int shmid;
key_t key=ftok("2048_client.c", 42);
if(key == -1) {
        printf("ftok failed");
        return -1;
    }
shared_mem *shm;

    if ((shmid = shmget(key, sizeof(msg), IPC_CREAT|0600)) < 0) {
        perror("shmget");
        exit(1);
    }

if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

msg=shm;

int direction = -1;
srand(time(NULL));

//SERVER SETS VALUES FOR SHARED MEMORY STRUCTURE

sem_wait(&msg->sem_server);

// setup the board
initialize();

// the board starts with 2 pieces
create_game_piece();
printf("pieces created");
create_game_piece();

msg->client=0;

int i;

for (i = 0; i < BOARD_SIZE * BOARD_SIZE; i++)
    msg->board[i] = board[i];

sem_post(&msg->sem_server);     

// game loop
while (1) {

    //CLIENT READS AND CHANGES VALUES

    //SERVER READS VALUES CHANGED BY CLIENT

    if (!move_board(direction))
        continue;

    sem_wait(&msg->sem_server);
    moves++;
    direction=msg->direction;

    if (check_win()) {
        print_board(-1);
        printf("congratulations! you've won in %d moves\r\n", moves);
        return 0;
    }

    create_game_piece();

    if (!has_moves_left()) {
        print_board(-1);
        printf("you lose! try again\r\n");
        //sleep(1);
        return 1;
    }
    sem_post(&msg->sem_server); 
}
int shmid;
key_t key=ftok("2048_client.c", 42);
if(key == -1) {
        printf("ftok failed");
        return -1;
    }
shared_mem *shm;
msg=(shared_mem *)malloc(sizeof(shared_mem));

    if ((shmid = shmget(key, sizeof(msg), IPC_CREAT|0600)) < 0) {
        perror("shmget");
        exit(1);
    }

  if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

atexit(on_exit2);
system("stty raw");

srand(time(NULL));

while (1) {

    // CLIENT READS VALUES CHANGED BY SERVER AND CHANGES THEM

    sem_wait(&msg->sem_server); 
    print_board(direction);

    direction = keypress();
    msg->direction=direction;
    sem_post(&msg->sem_server); 
}

共有1个答案

长孙星汉
2023-03-14

你的代码有很多问题。

  • 根本没有初始化信号量。对于信号量位于共享内存中的此操作,请确保将pshared参数设置为非零。
  • 您不能仅用一个信号量以这种方式进行双向同步(否则您将执行一个sem_post,该sem_post立即被同一进程sem_waited,因此该线程可能继续,而另一个线程无法运行)。
  • 您在客户机中malloc'了msg,但从未将其推送到共享内存中,因此共享内存仍未初始化。
  • 除了打开一大堆安全问题之外,您认为系统(“stty raw”)还能完成什么?
  • 显然它不是可运行的代码。我修好了很多小东西,但半小时后就放弃了,因为它有太多的问题。像将char*与shared_mem*进行比较这样的事情是错误的。在编译器上启用-wall和-wextra并修复所有得到的警告。您的代码充满了它,不幸的是,所有这些都表明了严重的问题。

从设计的角度来看,还有更多的问题。

显然,您使用的是服务器中全局的一维数组“board”。这是不恰当的,原因有二:

  • 板总是二维的,为什么不使用2D数组?
  • 您将其用作全局变量,所有函数都可以访问。这是“JavaScript”风格的编程。请将该板设置为本地主,并将其传递给各个函数。
 类似资料:
  • 程序应该创建200000个整数,并将2000个写入共享内存。分叉进程应该从共享内存中读取2000,父进程应该将下一个2000写入共享内存。 请帮帮我们谢谢你们 编辑:非常感谢您的回答。我不能标出正确的答案,因为我不知道什么是正确的。但我不想再尝试了。15个小时就够了

  • 我必须为C语言课程编写一个小游戏,它必须使用共享内存、信号量和一个可以处理多个客户机的客户机/服务器体系结构(游戏的确切要求是2)。 这两个客户机需要轮流执行,它们由完全相同的程序表示(这里没有涉及fork()--都以./client开头) 服务器必须在启动时创建所有资源。所以我的主要问题是关于信号量。(共享内存和游戏逻辑可以工作,或者并不难实现。) 为了决定服务器或客户机是否可以访问共享内存,我

  • 我的项目是在服务器上读取一个图像,进行一些处理,然后将整个图像传递给客户端。客户端接收图像并进行更多处理,然后将一些输出值返回给服务器。服务器和客户端之间使用的映像大小为[640x480x3]。 以下是我想到的实现这个问题的各种技术: 通过消息将整个像素值从服务器传递到客户端 在SO中有各种各样的答案。我目前正在努力让它工作。 服务器和客户端之间的这种消息传递模式是否可能?如果是,请提供一些文档参

  • 我想创建一个共享内存和信号量的C程序。应该有两个子进程。两个孩子都有一个不同的int数。然后有一个目标号码,应该写在共享内存中。现在两个孩子都应该从进球数中减去他们的数字,直到进球数低于或等于0。我不希望出现比赛条件。这就是为什么我尝试使用信号量。但对我没用。下面是我的代码:

  • 我在Linux上使用C。我需要构建使用共享内存和信号量进行通信的两个程序。 其中一个程序必须充当服务器(一次只能充当一个),另一个程序必须充当客户机(一次任意数量)。通信应遵循以下模式: 我知道如何在两个进程之间使用共享内存和信号量,但我不知道如何在数量不明的进程之间进行通信时使用它们。我考虑为每个客户机使用共享内存块,但我必须交换密钥并通知服务器新的客户机。所以这并不能解决问题。