Как обнаружить разъединение сокета TCP (с гнездом C Berkeley)

Я использую цикл для чтения сообщения из сокета ac Berkeley, но я не могу обнаружить, когда сокет отключен, поэтому я бы принял новое соединение. пожалуйста помоги

while(true) { bzero(buffer,256); n = read(newsockfd,buffer,255); printf("%s\n",buffer); } 

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

Получение ошибки при read()/recv() будет означать, что соединение нарушено, но не получение ошибки при чтении не означает, что соединение завершено.

Вам может быть интересно прочитать это: http://lkml.indiana.edu/hypermail/linux/kernel/0106.1/1154.html

Кроме того, использование TCP Keep Alive может помочь различать неактивные и поврежденные соединения (путем отправки чего-либо через регулярные интервалы, даже если нет данных, которые будут отправлены приложением).

(EDIT: Удалено неправильное предложение, как указано @Damon, спасибо.)

Ваша проблема в том, что вы полностью игнорируете результат, возвращаемый read() . Ваш код после read() должен выглядеть примерно так:

 if (n == 0) // peer disconnected break; else if (n == -1) // error { perror("read"); break; } else // received 'n' bytes { printf("%.*s", n, buffer); } 

И принятие нового соединения должно выполняться в отдельном streamе, не зависящем от конца streamа в этом соединении.

bzero() бессмыслен, просто обходной путь для предыдущих ошибок.

Это потому, что вы не использовали тайм-аут keepalive. В приемной стороне опция keepalive socket является лучшим решением для обнаружения мертвого соединения.

Но, в случае, если ваше приложение продолжает писать в сокет, есть что подумать больше. Даже если вы уже установили параметр keepalive в свой сокет приложения, вы не сможете своевременно определить состояние мертвого соединения сокета, в случае, если ваше приложение продолжает записывать в сокет. Это связано с повторной передачей tcp в стеке tcp ядра. tcp_retries1 и tcp_retries2 являются параметрами ядра для настройки тайм-аута повторной передачи tcp. Трудно предсказать точное время тайм-аута повторной передачи, потому что оно рассчитывается механизмом RTT. Вы можете увидеть это вычисление в rfc793. (3.7. Передача данных)

https://www.rfc-editor.org/rfc/rfc793.txt

На каждой платформе есть конфигурации ядра для повторной передачи tcp.

 Linux : tcp_retries1, tcp_retries2 : (exist in /proc/sys/net/ipv4) 

http://linux.die.net/man/7/tcp

 HPUX : tcp_ip_notify_interval, tcp_ip_abort_interval 

http://www.hpuxtips.es/?q=node/53

 AIX : rto_low, rto_high, rto_length, rto_limit 

http://www-903.ibm.com/kr/event/download/200804_324_swma/socket.pdf

Вы должны установить меньшее значение для tcp_retries2 (значение по умолчанию 15), если вы хотите раннее обнаружение мертвого соединения, но это не точное время, как я уже сказал. Кроме того, в настоящее время вы не можете установить эти значения только для одного сокета. Это глобальные параметры ядра. Было проведено некоторое испытание для применения опции сокета повторной передачи tcp для одиночного сокета ( http://patchwork.ozlabs.org/patch/55236/ ), но я не думаю, что он был применен в основной строке ядра. Я не могу найти такое определение параметров в файлах системных заголовков.

Для справки вы можете контролировать свой вариант сокета keepalive через «netstat -timers», как показано ниже. https://stackoverflow.com/questions/34914278

 netstat -c --timer | grep "192.0.0.1:43245 192.0.68.1:49742" tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (1.92/0/0) tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (0.71/0/0) tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (9.46/0/1) tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (8.30/0/1) tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (7.14/0/1) tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (5.98/0/1) tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (4.82/0/1) 

Кроме того, когда тайм-аут keepalive ocurrs, вы можете встретить разные события возврата в зависимости от используемых вами платформ, поэтому вы не должны определять статус мертвого соединения только событиями возврата. Например, HP возвращает событие POLLERR, и AIX возвращает событие POLLIN, когда происходит таймаут keepalive. В это время вы встретите ошибку ETIMEDOUT в вызове recv ().

В последней версии ядра (начиная с версии 2.6.37) вы можете использовать параметр TCP_USER_TIMEOUT, который будет работать хорошо. Эта опция может использоваться для одиночного сокета.

  • java.net.SocketException: сброс соединения
  • Как работает функция accept API ()?
  • close () не закрывает гнездо правильно
  • C # Установленное соединение было прервано программным обеспечением вашей хост-машины
  • Установка таймаута для операций сокета
  • Единство: streamовое видео в реальном времени
  • Сколько накладных расходов накладывает SSL?
  • Обработка частичного возврата из recv () TCP в C
  • как получить файл передачи между клиентом и сервером с помощью java socket
  • Содержит ли соединение сокетов TCP «поддерживать»?
  • Как использовать сокет-клиент с WCF (net.tcp)?
  • Interesting Posts

    Функция с тем же именем, но другая подпись в производном classе

    Простой в использовании инструмент для мониторинга входящего сетевого трафика

    eventlisteners, использующие hibernate 4.0 с весной 3.1.0.release?

    Заменить первое вхождение строки в Python

    Позиционирование содержимого элементов сетки в основном контейнере (функция субgradleа)

    Хранение изображений: DB или файловая система –

    Как отправить Ctrl + Alt + End на удаленный рабочий стол?

    Как преобразовать ANSI-кодированный файл в UTF-8 с помощью Notepad ++?

    Преобразование строки временной метки unix в удобочитаемую дату

    В чем разница между HashMap и TreeMap?

    Добавить водосточный желоб (привязка) к существующему файлу PDF

    Как заставить ассоциацию файлов в Windows 7? (Regedit?)

    Как экспортировать диаграмму в формате png в Excel 2010?

    Изменение положения popup popposts на основе X-позиции popover относительно края windows?

    Откройте хром и запустите страницу настроек

    Давайте будем гением компьютера.