GetQueuedCompletionStatus задерживается - PullRequest
0 голосов
/ 29 апреля 2011

Я написал сложную библиотеку для управления сетевым взаимодействием на основе механизма iocp.Проблема заключается в том, что когда сервер закрывает соединение, вызывая метод API closesocket (), эта информация иногда передается клиенту с задержкой на несколько секунд или даже минут.Мой код для обнаружения закрытия соединения выглядит следующим образом (упрощенно):

ok = GetQueuedCompletionStatus(completion_port, &io_size, (PULONG_PTR)&context, &overlapped, 40);

if (!ok) {
   // something went broken
  DWORD err = GetLastError();
  if (err == ERROR_CONNECTION_REFUSED) {
         // connection failed
  } else if (err == ERROR_SEM_TIMEOUT) {
        // connection timeout
  } else if (err == ERROR_NETNAME_DELETED) {
        // connection closure - point of interest
  } else if (err != WAIT_TIMEOUT) {
        // unknown error
  }
} else {
    // process incomming or outgoing data
}

Почему это происходит?Мне нужно знать о закрытии соединения немедленно, чтобы иметь возможность подключиться к серверу резервного копирования (не так сильно загружен - из-за этого происходит отключение).

Ответы [ 2 ]

1 голос
/ 30 апреля 2011

Как вы закрываете соединение?

Если вы просто звоните closesocket(), то вы запускаете последовательность завершения работы, которая будет пытаться гарантировать, что все данные, ожидающие в данный момент, достигнут пункта назначения. Это может занять время, особенно если сетевое соединение было перегружено, а датаграммы потеряны и происходит повторная передача TCP.

Если вы хотите немедленно закрыть соединение и потерять все ожидающие данные, установите linger на 0, а затем закройте сокет. Это выдаст RST для соединения, и вы получите это намного быстрее.

0 голосов
/ 01 мая 2011

Я пытался поэкспериментировать с параметром linger, как писал Лен, но это не помогло. Добавление вызова функции shutdown () незадолго до того, как closesocket () помогло мне. После анализа пакетов, достигающих сетевого интерфейса на клиенте (с WireShark), я обнаружил, что пакет RST был заменен пакетом FIN. Любопытно, что пакет RST не был задержан. Таким образом, операционная система знала, что соединение было закрыто, но по неизвестной причине эта информация была перенесена на прикладной уровень с очень большой задержкой. Я измерил задержки от 10 секунд до 4 минут.

...