Выключение Постоянный TCP Con. (C многопоточный сервер) - PullRequest
1 голос
/ 25 февраля 2011

Я проектирую многопоточный сервер с пулом потоков.Эта система предназначена для использования постоянных соединений TCP, так как клиенты будут поддерживать соединения близко к 24/7.Проблема, с которой я сталкиваюсь, состоит в том, как управлять выключениями.В настоящее время соединение приходит через "accept (listen_fd ....)" и получает назначение в структуру рабочего задания.Эта структура выгружается в рабочую очередь и принимается потоком.С этого момента эта тема посвящена текущему соединению.Мой код в потоке:

/* Function which runs in a thread to handle a request */
void *
handle_req( void *in)
{
  ssize_t n;
  char read;
  /* Convert the input to a workorder_ptr */
  workorder_t *workorder_ptr = (workorder_t *)in;

  while( !serv_shutdown
        && (n=recv(workorder_ptr->sock_fd,&read,1,0) != 0))
  {
    printf("Read a character: %c\n",read);
  }
  printf("Peer has shutdown.\n");

  /* Free the workorder memory */
  close(workorder_ptr->sock_fd);
  free(workorder_ptr);
  return NULL;
}

, который просто слушает сокет и бесконечно повторяет символы и работает правильно, когда клиент завершает соединение.Вы видите часть "! Serv_shutdown" в цикле while - это моя попытка заставить поток выйти из цикла при сигнале завершения работы.Когда перехватывается SIGINT, глобальная переменная устанавливается на 1. К сожалению, в настоящее время программа блокирует оператор recv и не будет проверять этот флаг, пока не будет прочитан другой символ.Я хочу избежать этого, так как может пройти произвольное количество времени, прежде чем другой символ будет отправлен по этому соединению.

Кроме того, я прочитал в другом посте, что лучше использовать «выбрать», чем «принять»ждать подключения к сокету, но я не совсем понял.Сделаете ли вы выбор, чтобы подождать, а затем сделать прием сразу после этого?Я не уверен, как select создает сокет-соединение.Я спрашиваю об этом, потому что, если мое понимание выбора прояснено, может быть, оно относится к вопросу, который я задаю?

Также также, как я могу обнаружить случай, когда соединение просто прерывается?

Спасибо!

РЕДАКТИРОВАТЬ Я думаю, что, возможно, наконец-то нашел решение после дальнейшего копания:

Пробуждение потока заблокировано при принятии() вызов

По сути, я мог бы создать глобальный канал и сделать так, чтобы каждый поток делал выбор для своего собственного socket_fd, а также этого глобального канала.Затем, когда сигнал пойман, я просто напишу что-нибудь в трубу.Все темы должны быть разбужены, нет?

Ответы [ 2 ]

1 голос
/ 12 ноября 2011

Вы можете использовать примитив recv(). Если он возвращает 0, это означает, что сокет был закрыт.

Дополнительная информация: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#recvman

1 голос
/ 05 мая 2011

Ну, во FreeBSD, MacOSX и, возможно, где-то еще есть вызов kevent (), который позволяет прослушивать широкий спектр системных событий, включая запросы на подключение и сигнализацию о поступлении данных в сокет.Это решит все ваши проблемы аккуратно, но не переносимо.Существуют такие библиотеки, как libevent и libev, которые обертывают специфические для ОС функции, такие как kevent () в BSD, epoll () в Linux и так далее.Может быть, это поможет вам.

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