cgccserver

gcc error, shareMemory undefined reference to?


server.h

// server.h
#ifndef SERVER_H
#define SERVER_H

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#define MAXLINE 256
#define MAX_PLAYERS 3

struct inventory {
    int seed[14];
    int corp[14];
    int booster;
};

struct Player {
    char name[MAXLINE];
    struct inventory inventory[MAXLINE];
    int money[MAXLINE];
    int active;
    int pid;
};

extern int playerCount;
extern struct Player* sharedMemory[MAX_PLAYERS];

#endif

server.c

//server.c
#include "server.h"

int playerCount = 0;
struct Player* sharedMemory[MAX_PLAYERS];

void sendSignalToClients();
void sendSignalToClients1();


int main() {
    int playerIndex = 0;
    key_t key;

    int keyFile = open("keyfile", O_RDWR | O_CREAT, 0666);
    if (keyFile == -1) {
        perror("keyfile");
        exit(EXIT_FAILURE);
    }

    if (read(keyFile, &key, sizeof(key)) != sizeof(key)) {
        key = ftok("/home/g_202010953/FARM/save", 1);
        write(keyFile, &key, sizeof(key));
    }

    close(keyFile);

    int shmid = shmget(key, sizeof(struct Player) * MAX_PLAYERS, 0666 | IPC_CREAT);
    if (shmid == -1) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < MAX_PLAYERS; ++i) {
        sharedMemory[i] = (struct Player*)shmat(shmid, NULL, 0);
        if (sharedMemory[i] == (struct Player*)-1) {
            perror("shmat");
            exit(EXIT_FAILURE);
        }
    }


    mkfifo("pipe", 0666);
    mkfifo("pipe1", 0666);
    int fd1 = open("pipe", O_RDONLY);
    int fd2 = open("pipe1", O_WRONLY);

    while (1) {
        char buffer[MAXLINE];
        read(fd1, buffer, sizeof(buffer));

        if (strcmp(buffer, "exit") == 0) {
            break;type here
        }

        
        if (playerCount < MAX_PLAYERS) {
            strcpy(sharedMemory[playerIndex]->name, buffer);
            sharedMemory[playerIndex]->active = 1;
            sharedMemory[playerIndex]->pid = getpid();
            playerIndex++;
            playerCount++;

            printf("player[%d] visit: %s\n", playerCount, buffer);
            sendSignalToClients1();
        }



        if (playerCount == MAX_PLAYERS) {
            sendSignalToClients();
        }


    }

    close(fd1);
    close(fd2);
    unlink("pipe");
    unlink("pipe1");


    for (int i = 0; i < MAX_PLAYERS; ++i) {
        shmdt(sharedMemory[i]);
    }

    return 0;
}

void sendSignalToClients() {
    pid_t* clientPid;

    for (int i = 0; i < MAX_PLAYERS; ++i) {
        if (sharedMemory[i]->active) {
            clientPid = (pid_t*)(&(sharedMemory[i]->pid));  
            kill(*clientPid, SIGUSR1);
        }
    }
}

void sendSignalToClients1() {
    pid_t* clientPid;

    for (int i = 0; i < MAX_PLAYERS; ++i) {
        if (sharedMemory[i]->active) {
            clientPid = (pid_t*)(&(sharedMemory[i]->pid));  
            kill(*clientPid, SIGUSR2);
        }
    }
}

client.c

//client.c
#include "server.h"

int fd1, fd2;
int num;

void select_conversation() {

    scanf("%d", &num);
    switch (num) {
    case 1:
        break;
    case 2:
        break;
    case 3:
        break;
    case 4:
        break;
    case 5:
        break;
    case 6:
        break;

    default:
        break;
    }
}
void handleSignal(int signum);

void handlePlayerNamesSignal(int signum);

int main() {
    key_t key;
    int shmid;
    int keyFile = open("keyfile", O_RDONLY);

    if (keyFile == -1) {
        perror("keyopen");
        exit(EXIT_FAILURE);
    }

    if (read(keyFile, &key, sizeof(key)) != sizeof(key)) {
        perror("keyfile");
        close(keyFile);
        exit(EXIT_FAILURE);
    }

    close(keyFile);

    shmid = shmget(key, sizeof(struct Player) * MAX_PLAYERS, 0666 | IPC_CREAT);
    if (shmid == -1) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < MAX_PLAYERS; ++i) {
        sharedMemory[i] = (struct Player*)shmat(shmid, NULL, 0);
        if (sharedMemory[i] == (struct Player*)-1) {
            perror("shmat");
            exit(EXIT_FAILURE);
        }
    }

    fd1 = open("pipe", O_WRONLY);
    fd2 = open("pipe1", O_RDONLY);

    if (fd1 == -1 || fd2 == -1) {
        perror("pipe error");
        exit(EXIT_FAILURE);
    }

    char playerName[MAXLINE];

    printf("input playername : ");
    fgets(playerName, MAXLINE, stdin);
    playerName[strcspn(playerName, "\n")] = '\0';

    write(fd1, playerName, sizeof(playerName));

    signal(SIGUSR2, handlePlayerNamesSignal);
    signal(SIGUSR1, handleSignal);

    for (int i = 0; i < MAX_PLAYERS; ++i) {
        shmdt(sharedMemory[i]);
    }


    close(fd1);
    close(fd2);

    return 0;
}


void handleSignal(int signum) {
    if (signum == SIGUSR1) {
        printf("SIGUSR1. maingame start.\n");
        select_conversation();
    }
}

void handlePlayerNamesSignal(int signum) {
    if (signum == SIGUSR2) {
        printf("SIGUSR2. player name list:\n");


        for (int i = 0; i < MAX_PLAYERS; ++i) {
            if (sharedMemory[i]->active) {
                printf("Player[%d] : %s\n", i + 1, sharedMemory[i]->name);
            }
        }
    }
}

When gcc -o client.c, undefined reference to `sharedMemory

I declared shared memory in the header file and defined it in server.c, but I don't know why this error appears.


Solution

  • I declared shared memory in the header file and defined it in server.c, but I don't know why this error appears.

    It appears because server.c is part of the server program only. Its definition of variable sharedMemory ensures that the server program has such a variable, but that does nothing for the separate client program. That needs its own definition of the object. Were it me, I would factor that out into a separate .c file, which I would then use in both programs.

    With that said, the architecture seems weird. You appear to be writing some kind of multiplayer game. In that case, the natural modes of operation would be either

    1. The server mediates all interactions between players, OR
    2. The players interact directly with each other.

    For case (1), I don't see why the client needs to access shared memory for the data of more than one player.

    For case (2), I don't see what role the server program is supposed to play, especially that needs access to player data.