Могу ли я неоднократно переключаться между блокирующим и неблокирующим поведением? - PullRequest
0 голосов
/ 29 мая 2018

У меня есть два процесса, которые общаются через доменные сокеты Unix в настройке первичной / реплики.Реплика должна периодически запрашивать у руководства первичную информацию, но она должна делать это только в том случае, если первичная организация указывает, что готова предложить указанную инструкцию.Если первичный сервер готов, реплика должна запросить первичный сервер и дождаться ответа;в противном случае он должен продолжить выполнение своей текущей задачи.

Обычно я бы использовал семафор POSIX, чтобы сообщить реплике, готов ли основной сервер - он быстрый и легкий.К сожалению, я работаю над исследовательской системой, которая не поддерживает общую память POSIX.Следовательно, Unix-сокеты - это все, что у меня есть.

Я знаю, что неблокирующие чтения выполняются довольно быстро, поэтому мне интересно, могу ли я сделать что-то вроде этого:

  • Открытьсоединение между репликой и основной.
  • Установите конец реплики неблокирующим.
  • Периодически проверяйте, может ли реплика читать с основной.
  • Если чтение завершается успешно, переключить сокет на блокировку и запросить основной .После завершения запроса возвращает сокет в неблокирующее состояние .
  • Если чтение не удалось, продолжайте до следующей проверки.

Можно ли повторно переключатьсясокет между блокирующим и неблокирующим поведением?

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

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

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

0 голосов
/ 29 мая 2018

Вы можете , используя fcntl:

int file_descriptor;
int flags;

// open file_descriptor

flags = fcntl(file_descriptor, F_GETFL, 0);
flags &= ~O_NONBLOCK;           // set blocking
flags |= O_NONBLOCK;            // set non-blocking
fcntl(file_descriptor, F_SETFL, flags);

Но я думаю, что ваша программа будет более простой, если вы просто используете два сокета.Используйте один для контроля (неблокирующий) и один для данных (блокирующий).Используйте сокет управления для передачи сообщений «готов» / «не готов» и сокет данных для «руководства».

Это устраняет необходимость многократно открывать / закрывать сокеты или изменять их конфигурацию и должно упроститьуправление потоками в вашей программе.Он также разделяет потоки данных и управления в ваших программах, что обычно является хорошей практикой.

...