Как правильно использовать неблокирующий сокет? [Дубликат]

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

11
задан herolover 9 June 2014 в 08:37
поделиться

1 ответ

Для асинхронного подключения вы должны использовать следующие шаги:

  • создать сокет с socket(..., SOCK_NONBLOCK, ...)
  • начать соединение с connect(fd, ...)
  • если возвращаемое значение равно ни 0, ни EINPROGRESS, а затем прервать с ошибкой
  • до тех пор, пока fd не будет считаться готовым к выходу
  • проверьте состояние сокета с getsockopt(fd, SOL_SOCKET, SO_ERROR, ...)
  • done

Нет циклов - если вы не хотите обрабатывать EINTR.

Если клиент запускается первым, вы должны увидеть ошибку ECONNREFUSED на последнем шаге. Если это произойдет, закройте сокет и начните с начала.

Трудно сказать, что не так с вашим кодом, не видя больше деталей. Я полагаю, что вы не прерываете ошибки в своей check_socket операции.

29
ответ дан nosid 17 August 2018 в 13:47
поделиться
  • 1
    Я знаю, что это старый комментарий, но я просто хотел заметить, что мне пришлось ждать чтения, чтобы поймать ETIMEDOUT. Это произошло, когда SYN-ответ не был возвращен. Если бы я только ждал записи, сокет исчез бы из netstat (из состояния SYN_SENT), но я не получил бы уведомления о том, что сокет был доступен для записи, чтобы вызвать getockopt и найти ETIMEDOUT. Я также добавил вызов сразу после подключения к getsockopt, чтобы увидеть, есть ли какие-либо немедленные ошибки, доступные перед опросом. – DreamWarrior 10 June 2015 в 15:02
  • 2
    @DreamWarrior: Это странно. Взгляните на connect (2) и connect (3) и найдите poll. На обеих страницах руководства указано, что вы должны ждать указания, что socket доступен для записи . Можете ли вы представить минимальный пример, который показывает неожиданное поведение? – nosid 11 June 2015 в 20:02
  • 3
    состояния пользовательской страницы. «Можно выбрать (2) или опрос (2) для завершения, выбрав сокет для записи». Я предполагаю, что ключевым словом является «завершение». Поскольку он никогда не был завершен, так как он никогда не получал SYN-ACK (или RST, который завершает рукопожатие, но приводит к ошибке), он никогда не становится доступным для записи. – DreamWarrior 18 June 2015 в 19:21
  • 4
    Я тестировал это, выполняя неблокирующее подключение к порту 10000 на 1.1.1.1. Однако мой код использовал планировщик Xt (через XtAppAddInput w / XtInputWriteMask), чтобы выполнить выбор / опрос, поэтому я не уверен, что он использовал, я просто знаю, что событие записи никогда не запускалось ». Событие чтения, добавленное с помощью XtInputReadMask, срабатывало, когда стек TCP был приурочен к ожиданию SYN-ACK. В этом случае getsockopt возвратил ETIMEDOUT. Я задаюсь вопросом, есть ли другие ошибки, которые будут отправляться только на чтение, но я не знаю, как их провоцировать; Я могу только проверить ECONNREFUSED и ETIMEDOUT. – DreamWarrior 18 June 2015 в 19:22
  • 5
    @DreamWarrior: Я не могу воспроизвести описанную вами проблему. Я написал минимальную тестовую программу , и она правильно сообщает ETIMEDOUT, используя POLLOUT. – nosid 19 June 2015 в 18:57
Другие вопросы по тегам:

Похожие вопросы: