Появился у меня глючный китайский PCI WiFi адаптер TP-LINK 150Mbps Wireless N Adapter (PCI\VEN_168C&DEV_002D). Не то чтобы совсем глючный, с большего он работает вполне себе хорошо, но совершенно не любит p2p соединения: так и норовит перестать видеть роутер при запущенном uTorrent'e. Другими словами, мой WiFi-адаптер, то и дело пишет "соединение ограничено", хотя на других устройствах WiFi работает замечательно и роутер ни при чём. Уж не знаю почему так происходит, вот только перестановка дров ничего не дала. Однако, было замечено, что достаточно переподключиться к беспроводной сети и проблема на время исчезает. Но есть загвоздка: т.к. соединение не рвётся, выключать и включать соединение надо вручную. Чтож, займёмся нашим любимым делом, проектированием "костылей".
Т.к. каждый раз лазить в "Центр управления сетями и общим доступом" надоедает, был написан следующий скрипт:
Т.е., когда сеть переставала работать, я просто запускал bat-файл, который выключал беспроводной интерфейс, затем включал его, тот на автомате цеплялся к моей точке доступа и сеть подымалась. Подробнее о данном срипте в этой статье .
Но, очень скоро мне надоело делать и это. К тому же, для поднимания сети требуется участие человека, что не совсем подходит, когда хочешь запустить торрент на ночь.
Значит, нам нужна программа, которая пинала бы адаптер (перезапускала интерфейс) в случае проблем. Исходя из функций, назовём эту программу "KickNetwork".
Программа KickNetwork должна выполнять следующие функции:
Первым делом создадим файл "KickNetwork.ini". Файл с настройками для нашей программы. В нём будет только одна секция, назовем её [General] и 4 параметра:
Работает, круто! Осталось поставить в автозагрузку.
Т.к. каждый раз лазить в "Центр управления сетями и общим доступом" надоедает, был написан следующий скрипт:
netsh interface set interface name="wireless" admin=disableгде name - имя сетевого подключения. По-умолчанию обычно "Беспроводное соединение".
netsh interface set interface name="wireless" admin=enable
Т.е., когда сеть переставала работать, я просто запускал bat-файл, который выключал беспроводной интерфейс, затем включал его, тот на автомате цеплялся к моей точке доступа и сеть подымалась. Подробнее о данном срипте в этой статье .
Но, очень скоро мне надоело делать и это. К тому же, для поднимания сети требуется участие человека, что не совсем подходит, когда хочешь запустить торрент на ночь.
Значит, нам нужна программа, которая пинала бы адаптер (перезапускала интерфейс) в случае проблем. Исходя из функций, назовём эту программу "KickNetwork".
Программа KickNetwork должна выполнять следующие функции:
- Висеть резедентно в фоновом режиме и через некоторый промежуток времени проверять доступность сети (пинговать роутер).
- В случае, если все ОК, засыпать до следующей проверки.
- Если совсем не ОК, выключать заданный сетевой интерфейс и затем его включать (перезапускать).
- Для удобства настройки хранить в ini-файле.
Оппа, индус-стайл!
Далее будет представлен код, который с большой долей вероятности является индусским. Я предупредил.
Кстати, программа писалась под консоль на Delphi XE3 :) Вот такое извращение. Кому не нравится - идут лесом.
Первым делом создадим файл "KickNetwork.ini". Файл с настройками для нашей программы. В нём будет только одна секция, назовем её [General] и 4 параметра:
- HOST - адрес (или имя хоста для проверки связи);
- PORT - номер TCP-порта для проверки;
- WAIT - задержка между проверками (в миллисекундах);
- NETNAME - имя сетевого интерфейса (который надо "пинать").
[GENERAL]Собственно сам исходник на Delphi XE3 (пояснять не буду, кто понимает - хватит и комментариев в коде, благо код очень простой):
HOST=192.168.1.1
PORT=80
WAIT=60000
NETNAME=Wireless
program KickNetwork;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
WinApi.Windows, //библиотека WinApi (нам нужна ф-ция CreateProcess)
Web.Win.Sockets, //библиотека класса TTcpClient
System.Inifiles; //библиотека класса TIniFile
//определение каталога Windows
function GetWindowsDir: string;
var
p : PChar;
begin
GetMem(p, MAX_PATH);
result := '';
if GetWindowsDirectory(p, MAX_PATH) > 0 then
result := string(p);
FreeMem(p);
end;
//функция выполнения консольной команды с ожиданием
function ExecAndWait(const FileName, Params: ShortString; const WinState: Word): boolean; export;
var
StartInfo: TStartupInfo;
ProcInfo: TProcessInformation;
CmdLine: ShortString;
begin
CmdLine :=Filename+ Params;
FillChar(StartInfo, SizeOf(StartInfo), #0);
with StartInfo do
begin
cb := SizeOf(StartInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := WinState;
end;
Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(Filename)),StartInfo,ProcInfo);
if Result then
begin
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
{ Free the Handles }
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end;
end;
//функция проверки доступности хоста
function TryToConnect(host: string; port: integer): boolean;
var
TCPClient: TTcpClient; //простейший TCP-клиент
begin
TCPClient:=TTcpClient.Create(NIL); //инициализируем компонент TCP-сервера
//задаём парамтры подключения
TCPClient.RemoteHost:=host;
TCPClient.RemotePort:=IntToStr(port);
//Пробуем поключиться
if TCPClient.Connect then Result:=True //Возвращаем TRUE в случае успеха
else Result:=False; //Возвращаем FALSE в случии неудачи
//разъединяемся
TCPClient.Disconnect;
TCPClient.Destroy;
end;
//процедура "пинания" сетевого интерфейса:
procedure KickNet(Network: string);
begin
//перезапускаем интерфейс:
ExecAndWait(GetWindowsDir+'\System32\netsh.exe interface set interface name="'+Network+'" admin=disable','',SW_HIDE);
ExecAndWait(GetWindowsDir+'\System32\netsh.exe interface set interface name="'+Network+'" admin=enable','',SW_HIDE);
end;
var
IFile: TIniFile; //переменная для работы с ini-файлом
PingHost: string; //хост для проверки соединения
PingPort: Integer; //порт хоста для проверки соединения
WaitTime: Integer; //таймаут между проверками
NetworkName: string; //имя сетевого интерфейса для "пинания"
begin
try
//читаем настройки из файла KickNetwork.ini
IFile:=TIniFile.Create(GetCurrentDir+'\KickNetwork.ini');
PingHost:=IFile.ReadString('GENERAL','HOST','192.168.1.1');
PingPort:=StrToInt(IFile.ReadString('GENERAL','PORT','80'));
WaitTime:=StrToInt(IFile.ReadString('GENERAL','WAIT','60000'));
NetworkName:=IFile.ReadString('GENERAL','NETNAME','Wireless adapter');
while True do //цикл
begin
//Подключаемся, если не выходит то пинаем
if not TryToConnect(PingHost,PingPort) then KickNet(NetworkName);
Sleep(WaitTime); //в любом случае засыпаем
end;
{ TODO -oUser -cConsole Main : Insert code here }
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Работает, круто! Осталось поставить в автозагрузку.
супер!
ОтветитьУдалить