Попытка инициализировать новую структуру для каждого соединения в программе сервер-клиент без перезаписи предыдущего - PullRequest
0 голосов
/ 26 октября 2019

Итак, в основном у меня есть клиент-серверная программа чата, использующая сокеты и потоки, которые могут содержать несколько клиентов. То, что я пытаюсь сделать, это при подключении клиента сервер передает эту вновь созданную клиентскую структуру в связанный список, чтобы была запись каждого подключенного пользователя. Но кажется, что после того, как первый пользователь подключен и добавлена ​​структура, второй подключается и перезаписывает его.

typedef struct client client_t;
typedef struct node node_t;

node_t *client_list = NULL;

struct client {
    int ID;
    int sockID;
};

struct node {
    client_t *client;
    node_t *next;
};

node_t * node_add(node_t *head, client_t *c) {
    node_t *new = (node_t *)malloc(sizeof(node_t));
    if (new == NULL) {
        return NULL;
    }
    new->client = c;
    new->next = head;
    return new;
}

int main() {

    while(1) {
        client_t client;
        client.sockID = accept(server_socket, (struct sockaddr *) &client.clientaddress, &client.len);
        client.ID = client_count + 1;

        if (pthread_create(&thread[client_count], NULL, network, (void *) &client) == 0) {
            node_t *new = node_add(client_list, &client);
            client_list = new;
       }
    }
    return 0;
}

Я представляю тот факт, что я объявляю 'client_t client' и просто перезаписываю предыдущее новым соединением. Есть ли способ обойти это, если я не хочу жестко кодировать имя каждого клиента ..

1 Ответ

0 голосов
/ 26 октября 2019

Вам нужно будет изучить модель памяти C более внимательно. Ваш код содержит ошибку, типичную для новых программистов на Си. Требуемая структура данных выглядит примерно так:

struct node {
    client_t client;  // Not a pointer!
    node_t *next;
};

Как вы уже определили, узел хранит только указатель на client_t. Вы выделяете client_t как локальную (C auto) переменную и передаете указатель на нее в распределитель узлов, но эта локальная переменная имеет область действия, которая заканчивается после каждой итерации цикла.

С новым определением запись клиента в узле сохраняется до тех пор, пока вы явно не free() it.

Соответствующим обновлением для распределителя узлов будет

node_t * node_add(node_t *head, client_t *c) {
    node_t *new = (node_t *)malloc(sizeof(node_t));
    if (new == NULL) {
        return NULL;
    }
    new->client = *c; // Copy the entire client into the node.
    new->next = head;
    return new;
}

закомментированная строка является struct присваиванием. Он копирует оба поля client_t в узел.

Чтобы использовать клиентскую информацию, которая теперь хранится в узле, вы будете использовать . вместо ->: например, node->client.ID.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...