简体   繁体   中英

Client server program with shared memory and semaphores in C

I don't really understand how shared memory works and I am trying to write a server-client program in which the server and client talk to each other using shared memory and semaphores.

Shared memory structure:

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;

Server:

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

Client:

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

Could someone please tell me how to coordinate the way the client and server access the shared memory so that it works according to the comments in the code?

SHM_UNLOCK does not do what you think. It tries to lock pages in memory not prevent access. You need a semaphore to control access to the shared memory. See semctl, semget, etc., and employ them in both the client and server for mutually exclusive access.

There are a lot of things wrong with your code.

  • You did not initialize the semaphore at all. For this operation where the semaphore is located in shared memory, make sure to set the pshared argument to nonzero.
  • You cannot do two-way synchronization this way with only one semaphore (otherwise you do a sem_post, that is immediately sem_waited by the same process, hence that thread may continue, the other one doesn't get to run).
  • You malloc'ed msg in the client, and never pushed it to the shared memory, thus the shared memory is still not initialized.
  • What do you think system("stty raw") is going to accomplish, other than opening a seriously big can of security issues?
  • Obviously it wasn't runnable code. I've fixed quite a few small things, but gave up after half an hour because there's just too much wrong with it. Things like comparing a char* to a shared_mem* is wrong. Enable -Wall and -Wextra on your compiler and fix all warnings you get. Your code is full of it and unfortunately all indicate serious issues.

From a design perspective, there are even more issues.

Apparently you are using a 1-D array 'board' that is global in the server. This is not proper for two reasons:

  • The board is always 2-dimensional, why not use a 2D array?
  • You use it as a global variable, accessible by all functions. This is "javascript"-style programming. Please make the board local to main and pass it to the various functions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM