C TCP / IP Sockets: как синхронизировать входные данные из клиентских сокетов с серверным сокетом, который должен чередоваться - PullRequest
0 голосов
/ 03 февраля 2019

У меня есть программа, которую в конечном итоге я хочу превратить в игру клиент-сервер в крестики-нолики, но в настоящее время я просто проверяю связь с отправкой и печатью сообщений.Я в порядке до того момента, когда сервер получает сообщения от нескольких клиентов, но все это терпит неудачу, когда я пытаюсь заставить его переключаться между клиентами, как при получении ввода от клиента 1, затем клиента 2, затем 1 снова и т. Д. ЯЯ уверен, что я просто поступаю об этом очень неправильно.

Вот код, формирующий соединения и общающийся с клиентами.

listen(sockfd,5);
clilen = sizeof(cli_addr);


//client1
clientsockfd[0] = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (clientsockfd[0] < 0) {
  perror("ERROR on accept");
  exit(1);
}

//client2
clientsockfd[1] = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (clientsockfd[1] < 0) {
  perror("ERROR on accept");
  exit(1);
}

while (1) {

  //create child process for each client
  pid1 = fork();
  if (pid1 < 0) {
     perror("ERROR on fork");
     exit(1);
  }

  //client1
  if (pid1 == 0) {
     /* This is the client process */
     close(sockfd);
     doprocessing(clientsockfd[i]);

  }
  //client2
  if(pid2 == 0){
      close(sockfd);
      doprocessing(clientsockfd[i]);
      //functions
  }

  i++;

}

Я также пытался во второй раз разветвляться внутри первого разветвления, но он такжеСбой.

Здесь часть client.c, касающаяся связи с сервером.

 if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
   perror("Error connecting: ");
   exit(1);
}

while(1){

      //ask for message to be read by server
      printf("Please enter the message: ");
      bzero(buffer,256);
      fgets(buffer,255,stdin);

      // send message
      n = write(sockfd, buffer, strlen(buffer));

      if (n < 0) {
         perror("Error writing to socket: ");
         exit(1);
      }

      //empty buffer
      bzero(buffer,256);

      //read reply from server
      n = read(sockfd, buffer, 255);
      if (n < 0) {
         perror("Error reading from socket: ");
         exit(1);
      }

      printf("%s\n",buffer);
}
return 0;
}

Также здесь есть функция обработки в случае необходимости

void doprocessing (int sock) {
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);

if (n < 0) {
  perror("ERROR reading from socket");
  exit(1);
}

printf("Here is the message: %s\n",buffer);
n = write(sock,"I got your message",18);

if (n < 0) {
  perror("ERROR writing to socket");
  exit(1);
}

}

Что я получаю при запуске программы: При подключении второго клиента существует бесконечный цикл, где:

ОШИБКА чтения из сокета: Неверный дескриптор файла

повторяется много раз, затем:

ОШИБКА на развилке: ресурс временно недоступен

появляется дважды, и, наконец,

ОШИБКА чтения из сокета: Ошибка ввода / вывода

повторяется бесконечно, пока я не принудительно завершу программу.Если я пропустил какую-либо информацию, пожалуйста, дайте мне знать, и я добавлю ее.Спасибо.

1 Ответ

0 голосов
/ 03 февраля 2019
    while (1) {
        pid = fork();
        ....
        i++;
    }

создает слишком много дочерних процессов, что в итоге приводит к сбою разветвления.

Каждый дочерний процесс использует clientsockfd[i];только два из них фактически выделены.Между тем i растет к бесконечности;третий процесс уже получает сокет мусора (это также внешний доступ, следовательно, UB), который объясняет ошибки ввода-вывода.

Рассмотрим вместо этого разветвление клиентов один раз и

    while (1) {
       doprocessing(clientsockfd[0]);
       doprocessing(clientsockfd[1]);
    }

в магистрали.

...