2017-01-08 6 views
0

Я ищу способ получить сигнал на порту завершения ввода-вывода, когда сокет становится читаемым/записываемым (т. Е. Следующий send/recv будет завершен немедленно). В принципе, я хочу перекрытую версию WSASelect.Есть ли способ использовать IOCP для уведомления, когда сокет читается/записывается?

(Да, я знаю, что для многих приложений это необязательно, и вы можете просто продолжать выдавать перекрывающиеся вызовы send. Но в других приложениях вы хотите отложить создание сообщения для отправки до последнего момента, как обсуждалось e.g. here В этих случаях полезно выполнить (a) дождаться, когда сокет будет записываться, (b) сгенерировать следующее сообщение, (c) отправить следующее сообщение.)

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

+1

вам не нужно все это. после подключения сокета он все время «записывается» и «читается». вы можете иметь множественную перекрывающуюся отправку по времени. однако только один recv-запрос во времени имеет смысл. вам нужно сделать recv сразу после подключения, а затем после завершения предыдущего recv. до разъединения. «будет немедленно завершено» - при использовании асинхронного io это не имеет смысла – RbMm

+0

Мне это нужно и объяснил, почему в вопросе - это способ минимизировать буферизацию отправки для приложений, чувствительных к задержкам. (В качестве альтернативы я предполагаю, что было бы также хорошо, если бы был способ получить предупреждение, когда общий размер буфера отправки упал ниже некоторой отметки с низким уровнем воды, но я даже меньше надеюсь на это существующее ...) –

+1

, когда отправка завершена - вы сообщили об этом. например, когда вам нужно отправить большие данные - вы можете отправить только кусок. когда передача этого фрагмента завершена - вы получили уведомление в IOCP об этом, и внутри этого уведомления - отправьте еще один фрагмент. и т. д. Я уже много раз делаю это – RbMm

ответ

0

Для обнаружения того, что сокет читается, выясняется, что есть недокументированная, но хорошо известная часть фольклора: вы можете выдать «нулевое байтовое чтение», то есть перекрытие WSARecv с буфером приема с нулевым байтом , и это не будет завершено, пока не будут прочитаны некоторые данные. У этого есть been recommended для серверов, которые пытаются делать одновременные чтения из большого количества в основном бездействующих сокетов, чтобы избежать проблем с использованием памяти (очевидно, приемные буферы IOCP привязаны к ОЗУ). Пример этого метода можно увидеть в исходном коде libuv. Они также имеют дополнительную доработку, которая заключается в том, что для использования с сокетами UDP они выдают нулевой байтовый прием с набором MSG_PEEK. (Это важно, потому что без этого флага прием с нулевым байтом будет потреблять пакет, обрезая его до нулевых байтов.) MSDN утверждает, что вы не можете комбинировать MSG_PEEK с перекрывающимися вводами-выводами, но, видимо, это работает для них ...

Конечно, это только половина ответа, потому что все еще существует вопрос об обнаружении возможности записи.

Возможно, что подобный трюк с «нулевым байтом» будет работать? (Используется непосредственно для TCP и добавляет флаг MSG_PARTIAL в сокеты UDP, чтобы избежать фактической отправки пакета с нулевым байтом.) Экспериментально я проверил, что попытка отправки нулевого байта в незаписываемом неблокирующемся TCP-сокете возвращает WSAEWOULDBLOCK, так что это многообещающий знак, но я не пробовал с перекрытием ввода/вывода. Я подойду к нему в конце концов и обновить этот ответ; или, альтернативно, если кто-то хочет попробовать его первым и опубликовать свой собственный консолидированный ответ, то я, вероятно, его приму. -

+0

Я бы сказал, что возможность записи является функцией размера io. Моя догадка заключается в том, что до тех пор, пока размер tcp-send-buffer минус комбинированные размеры незавершенных отправлений выше вашей полезной нагрузки, WSASend вернется в ожидании. Теперь это означает, что вы должны обрабатывать доработки достаточно быстро, чтобы ваша эвристика была актуальной, и что у вас есть представление о том, какой размер буфера отправки. Войдите в «Алго» Нагеля .... –

 Смежные вопросы

  • Нет связанных вопросов^_^