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

时间:2014-05-28 18:58:33

标签: c client-server posix semaphore shared-memory

我真的不明白共享内存是如何工作的,我正在尝试编写一个服务器 - 客户端程序,其中服务器和客户端使用共享内存和信号量相互通信。

共享内存结构:

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

有人可以告诉我如何协调客户端和服务器访问共享内存的方式,以便它根据代码中的注释工作吗?

2 个答案:

答案 0 :(得分:1)

SHM_UNLOCK不符合你的想法。它试图锁定内存中的页面而不阻止访问。您需要一个信号量来控制对共享内存的访问。请参阅semctl,semget等,并在客户端和服务器中使用它们以进行互斥访问。

答案 1 :(得分:1)

您的代码存在很多问题。

  • 您根本没有初始化信号量。对于这个操作所在的地方 信号量位于共享内存中,请确保将pshared参数设置为非零。
  • 只能使用一个信号量,不能以这种方式进行双向同步 (否则你会做一个sem_post,它会立即被sem_waited 进程,因此该线程可能会继续,另一个不会运行)。
  • 你在客户端中使用了mallg,并且从未将其推送到共享内存, 因此共享内存仍未初始化。
  • 除了打开一大堆安全问题外,您认为系统(“stty raw”)将会实现什么目标?
  • 显然它不是可运行的代码。我已经修好了一些小东西,但是半小时后就放弃了,因为它有太多的错误。比较char *和shared_mem *之类的东西是错误的。在编译器上启用-Wall和-Wextra并修复所有警告。你的代码充满了它,不幸的是,所有代码都表明了严重的问题。

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

显然,您正在使用服务器中全局的1-D阵列“电路板”。这有两个原因:

  • 电路板总是二维的,为什么不使用二维阵列?
  • 您可以将其用作全局变量,可供所有函数访问。这是“javascript”式编程。请将主板设为本地主机并将其传递给各种功能。