Как я могу записать некоторые данные с сервера на все мои клиенты, которые подключены к моему серверу? - PullRequest
0 голосов
/ 06 января 2020

У меня небольшая проблема, и я не нахожу никаких решений. У меня есть этот код.

Код сервера

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>

#define PORT 2908
extern int errno;

typedef struct thData{
    int idThread; 
    int cl; 
}thData;

static void *treat(void *); 
void raspunde(void *);

int main ()
{
  struct sockaddr_in server;    
  struct sockaddr_in from;  
  int nr;       
  int sd;       
  int pid;
  pthread_t th[100];
    int i=0;



  if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
    {

      return errno;
    }
  int on=1;
  setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));

  bzero (&server, sizeof (server));
  bzero (&from, sizeof (from));

    server.sin_family = AF_INET;    
    server.sin_addr.s_addr = htonl (INADDR_ANY);
    server.sin_port = htons (PORT);

  /
  if (bind (sd, (struct sockaddr *) &server, sizeof (struct sockaddr)) == -1)
    {

      return errno;
    }


  if (listen (sd, 2) == -1)
    {
      perror ("[server]Error at listen().\n");
      return errno;
    }

  while (1)
    {
      int client;
      thData * td;     
      int length = sizeof (from);


      fflush (stdout);


      if ( (client = accept (sd, (struct sockaddr *) &from, &length)) < 0)
    {
      perror ("[server]Error at accept().\n");
      continue;
    }

    td=(struct thData*)malloc(sizeof(struct thData));   
    td->idThread=i++;
    td->cl=client;

    pthread_create(&th[i], NULL, &treat, td);         

    }//while    
};              
static void *treat(void * arg)
{       
        struct thData tdL; 
        tdL= *((struct thData*)arg);    
        printf ("[thread]- %d - Waiting the message...\n", tdL.idThread);
        fflush (stdout);         
        pthread_detach(pthread_self());     
        raspunde((struct thData*)arg);
        close ((intptr_t)arg);
        return(NULL);   

};


void raspunde(void *arg)
{
        int nr, i=0;
    struct thData tdL; 
    tdL= *((struct thData*)arg);
    if (read (tdL.cl, &nr,sizeof(int)) <= 0)
            {
              printf("[Thread %d]\n",tdL.idThread);
              perror ("Error at read() from client.\n");

            }

    printf ("[Thread %d]The message is...%d\n",tdL.idThread, nr);


              nr++;      
    printf("[Thread %d]Sending the message back...%d\n",tdL.idThread, nr);

        printf("%d\n",tdL.cl );
     if (write (tdL.cl, &nr, sizeof(int)) <= 0)
        {
         printf("[Thread %d] ",tdL.idThread);
         perror ("[Thread]Error at write() from client.\n");
        }
    else
        printf ("[Thread %d]The message was sent.\n",tdL.idThread); 

}

Приведенный выше код является сервером, который создает для каждого клиента поток. Клиент отправляет число на сервер, и сервер ответит клиенту с увеличением числа на 1.

Вопрос в том, как мне написать, например, nr из функции ответа или строковое сообщение для все мои клиенты, которые подключены на моем сервере?

Заранее спасибо!

1 Ответ

0 голосов
/ 08 января 2020

Как указано в комментариях, вам нужно будет вести список активных тем (защищенных мьютексом!), Чтобы знать, кто подключен к вашему серверу. Когда поток создан, он будет добавлен в список, а когда выполнение завершится, он сам удалится. Таким образом, вы можете внести следующие изменения:

  1. Создать глобальный список потоков и pthread_mutex_t для его защиты (это может произойти в main)
  2. Создать функцию для вставки поток к списку и функция для удаления потоков. Не забудьте взять мьютекс перед изменением списка и освободить его после.
  3. Добавьте вставку в функцию treat в качестве первой инструкции и добавьте функцию удаления до close (чтобы предотвратить отправку к закрытому соединению)
  4. Определите функцию широковещания, которая принимает сообщение, проходит по глобальному списку и отправляет сообщение каждому клиенту. Опять же, не забудьте взять мьютекс во время цикла по списку и отпустить его, когда закончите. Возможно, вы также захотите пропустить отправителя трансляции.

Самый простой способ реализовать это - использовать односвязный список, в который вы всегда вставляете заголовок (для быстрой вставки). ) и удалить элементы по их идентификатору. Заголовки функций должны выглядеть следующим образом:

// your linked list
list_t* threadList;
pthread_mutex_t mutex;

void insert_list(thData* th);

// This could also return void, since to know the id you must already have the data that will be returned
thData* remove_list(int id);

// msg can have any type
void broadcast(int msg, int broadcasterId);
...