Обнаружение загрузки сетевого стека в Win 7
Я использую встроенную win 7 с замененным проводником, чтобы система загружалась прямо в мое приложение.
Я обнаружил, что к тому моменту, когда мое приложение запускается, сетевой стек не готов, и мне не удается привязаться к каким-либо сетевым адресам. К сожалению, это не простые сетевые требования с множеством разных резьбовых частей, начинающихся в разное время. Существует подключаемая система, которая может запускать сетевые интерфейсы, интерфейс telnet, широковещательный поток UDP-обнаружения и т. Д.
Есть ли простой способ, когда мое приложение начинает обнаруживать, работает ли сетевой стек?
Приложение в основном Delphi, использующее компоненты Indy (но плагины C++, использующие asio).
В настоящее время чит-решение состоит в том, чтобы перед сном "Application.Initialize" поставить 4-секундный сон, и он всегда запускается правильно. Если я помещаю сон после "Application.Initialize", это говорит мне о том, что есть компоненты, которые выполняют WSAStartup в своей процедуре инициализации, и это то, что ломает вещи.
2 ответа
Проблема оказалась не в сетевом стеке, а в специфических интерфейсах. При запуске различных сетевых компонентов они пытались привязаться к доступным портам. Поскольку приложение запускалось так быстро, физические порты были недоступны и ничто не было связано.
Решение состояло в том, чтобы написать сырую подпрограмму winsock, чтобы получить список доступных портов и подождать, пока число портов> 1 (необходимо учитывать обратную связь) в самом начале приложения.
Для справки это API, который я использовал для получения списка интерфейсов:
WSAIoctl(fSocket, SIO_GET_INTERFACE_LIST, Nil, 0, @InterfaceList, sizeof(InterfaceList), @BytesRet, Nil, Nil);
Переведите ожидающий вызов в WSAStartup
в initialization
раздел одного из вашего устройства, пока сеть не будет успешно инициализирована.
unit NetworkWaitUnit;
interface
implementation
uses
Windows,
yourWinSockUnit;
var
WsaDataOnce: TWSADATA;
const
WinsockLevel = $0202;
initialization
while not WSAStartup(WinsockLevel, WsaDataOnce) do
sleep(100);
end.
Затем убедитесь, что этот блок указан первым в .dpr uses
список объектов. В результате он будет вызываться раньше всех других модулей, и ваша программа должна работать как положено.
Нечто похожее на это:
program MyServer;
uses
NetworkWaitUnit, // should be listed first to be called first
SysUtils,
...
end.