-
Проблема: получаю данные по телнет протоколу из инета: Сделал:
TelnetSocket: TClientSocket;
...
procedure TTelnetForm.ClientOnError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: integer);
var
ErrStr: string;
begin
case ErrorEvent of
eeGeneral: ErrStr := 'General Error';
eeSend: ErrStr := 'Send Error';
eeReceive: ErrStr := 'Receive Error';
eeConnect: ErrStr := 'Connect Error';
eeDisconnect: ErrStr := 'Disconnect Error';
eeAccept: ErrStr := 'Accept Error';
eeLookup: ErrStr := 'Lookup Error';
end;
SetLength(TelnetText, Length(TelnetText) + 1);
TelnetText[Length(TelnetText)-1] := 'Error Type : ' + ErrStr +
', Error Code : ' + IntToStr(ErrorCode);
ErrorCode := 0;
TelnetSocket.Close;
FindNextTelnetServer;
end;
...
procedure TTelnetForm.FindNextTelnetServer;
begin
if (not TelnetTable.Eof) and (TelnetTable.FindNext) then
begin
TelnetSocket.Host := TelnetTableAddress.AsString;
TelnetSocket.Port := TelnetTablePort.Value;
TelnetSocket.Active := True;
end
else
begin
SetLength(TelnetText, Length(TelnetText) + 1);
TelnetText[Length(TelnetText)-1] := 'Can not find working server!';
CopyTelnetStrToTelnetWindows;
if TelnetSocket.Active then
TelnetSocket.Close;
end;
end;
Проблема заключается в том, что если первый сервер в списке недоступен, он и к остальным поключится не может. Пишет Error Type : Connect Error, Error Code : 10049
-
1. Замени TelnetSocket.Close;
на Socket.Close; 2. Убери из обработчика OnError непосредственный вызов FindNextTelnetServer Вместо этого посылай окну формы любое предопределенное асинхронное сообщение, в обработчике которого собссно и вызывай FindNextTelnetServer
-
Спасибо за совет. Заменил на SocetClose. Заменил в ClientOnError прямой вызов FindNextTelnetServer на PostMessage, с последущим вызовом в обработке этого сообщения FindNextTelnetServer. Однако ничего не изменилось...
-
Т.е. все попытки подключения приводят к отказу с кодом 10049 ?
-
Да, а вот ставишь первым работающий сервер - прекрасно соединяется. Причем что заметил: для проверки делаешь список адресов серверов: не работающий работающий не работающий и т.д. При обращении к нерабочему адресу как положено несколько секунд его опрашивает, потом выдает Lookup Error (что верно), а при обращении к точно рабочему - прям сразу выкидывает 10049, и т.д.
-
Сейчас попробовал: а если сделать так: не работающий сервер работающий работающий
то первый работающий сервер выдает ошибку 10049, а второй подсоединяется нормально, даже если это один и тот же сервер.
-
> к нерабочему адресу
> выдает Lookup Error (что верно)
Да вот как раз и не верно. Lookup Error - ошибка, возникающая не при недоступности хоста, а при невозможности разрешить имя хоста в его адрес.
А под "нерабочим адресом", насколько я понял, ты подразумеваешь IP-адрес хоста, недоступного по каким-то причинам на момент обращения к нему.
-
> даже если это один и тот же сервер
Это как ?
Давай уже приводи список в том виде, в котором данные из него при каждой итерации попадают в св-ва Host и Port компонента непосредственно перед тем как он переводится тобой в состояние Active=True ..
-
То Сергей М. Для проверки набиваю любой несуществующий адрес. От правильно ругается - Lookup error - он его не находит. Так вот если сразу после этого, хоть в ручную, по нажантю на кнопку, хоть при вызове PostMessage из ф-ции ClientOnError при соединении с существующим адресом 1-й раз он напишет 10049 ошибку, второй раз - соединиться. Для проверки делал очень просто: создал для пробы 3 кнопки с такого вида кодом
if TelnetSocket.Active then
TelnetSocket.Socket.Close;
TelnetSocket.Host := <здесь в каждой кнопке пишу адрес сервера>;
TelnetSocket.Port := 23;
TelnetSocket.Active := True;
Первая - с несуществующим адресом, 2 другие - с существующим. Если нажимаю на существующий адрес - соединение есть. Не существующий - Lookup error, опять существующий - ошибка 10049, снова нажимаю эту же кнопку - соединение есть! Т.е. такое впечатление что при неудачной попытке ошибка не сбрасывается, а сбрасывается только при обращении к существующему адресу.
-
> <здесь в каждой кнопке пишу адрес сервера>
Может все же не адрес сервера, а имя хоста ?
-
ну имелось ввиду именно имя хоста. да и еслиб что то не верно было, он бы вообще не соединял...
-
> имелось ввиду именно имя хоста
Тогда что есть "нерабочий адрес", если в твоем списке не адреса, а имена хостов ?
-
В общем привожу полный код тестовой программы. Форма - на ней 2 кнопки и мемо. Button1 - с несуществующим адресом, Button2 - с работающим.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
procedure ClientOnConnected(Sender: TObject; Socket: TCustomWinSocket);
procedure ClientOnConnecting(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientOnDisconnected(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientOnError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: integer);
procedure ClientOnRead(Sender: TObject; Socket: TCustomWinSocket);
public
end;
var
Form1: TForm1;
TelnetSocket: TClientSocket;
implementation
procedure TForm1.ClientOnConnecting(Sender: TObject; Socket: TCustomWinSocket);
var
S: string;
begin
if TelnetSocket.Host = '' then
S := TelnetSocket.Address
else
S := TelnetSocket.Host;
Memo1.Lines.Add('Connecting to server [' + S + ']');
end;
procedure TForm1.ClientOnConnected(Sender: TObject; Socket: TCustomWinSocket);
var
Connectcall, S: string;
begin
if TelnetSocket.Host = '' then
S := TelnetSocket.Address
else
S := TelnetSocket.Host;
Memo1.Lines.Add('Server of connected : ' + S);
TelnetSocket.Socket.SendText('RX4HX' + #10 + #13);
end;
procedure TForm1.ClientOnDisconnected(Sender: TObject; Socket: TCustomWinSocket);
var
S: string;
begin
if TelnetSocket.Host = '' then
S := TelnetSocket.Address
else
S := TelnetSocket.Host;
Memo1.Lines.Add('Disconnected from server [' + S + ']');
end;
procedure TForm1.ClientOnRead(Sender: TObject; Socket: TCustomWinSocket);
begin
Memo1.Lines.Add(Socket.ReceiveText);
end;
procedure TForm1.ClientOnError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: integer);
var
ErrStr: string;
begin
case ErrorEvent of
eeGeneral: ErrStr := 'General Error';
eeSend: ErrStr := 'Send Error';
eeReceive: ErrStr := 'Receive Error';
eeConnect: ErrStr := 'Connect Error';
eeDisconnect: ErrStr := 'Disconnect Error';
eeAccept: ErrStr := 'Accept Error';
eeLookup: ErrStr := 'Lookup Error';
end;
Memo1.Lines.Add('Error Type : ' + ErrStr +
', Error Code : ' + IntToStr(ErrorCode));
ErrorCode := 0;
Socket.Close;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TelnetSocket := TClientSocket.Create(Self);
TelnetSocket.OnConnecting := ClientOnConnecting;
TelnetSocket.OnConnect := ClientOnConnected;
TelnetSocket.OnDisconnect := ClientOnDisconnected;
TelnetSocket.OnRead := ClientOnRead;
TelnetSocket.OnError := ClientOnError;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
TelnetSocket.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if TelnetSocket.Active then
TelnetSocket.Socket.Close;
TelnetSocket.Host := '1yu1exy.org';
TelnetSocket.Port := 8000;
TelnetSocket.Active := True;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if TelnetSocket.Active then
TelnetSocket.Socket.Close;
TelnetSocket.Host := 'rn6bn.73.ru';
TelnetSocket.Port := 23;
TelnetSocket.Active := True;
end;
end.
Нажмите на Button2 - произойдет соединение с сервером. Затем нажмите на Button1 - выдаст ошибку Lookup server. Нажмите опять на Button2 - видаст ошибку 100049 и опять на Button2 - произойдет соединение.
-
однако все заработало, если сделать так:
procedure TForm1.Button2Click(Sender: TObject);
begin
if Assigned(TelnetSocket) then
begin
FormDestroy(nil);
TelnetSocket := nil;
end;
FormCreate(nil);
TelnetSocket.Host := 'rn6bn.73.ru';
TelnetSocket.Address := '';
TelnetSocket.Port := 23;
TelnetSocket.Active := True;
end;
Т.е. перед повторным использованием нужно уничтожать и снова создвать... Не уверен, что это верно..
-
при Lookup-отказе не выполняй Socket.Close
Ситуация изменилась ?
-
Убрал Socket.Close везде вообще... Нет, ничего не изменилось. Блин! Все перепробовал! Замкнутый круг какой то.... Но ведь обычный виндовый telnet все нормально отрабарывает....
-
Мда .. это засада..
завтра подскажу как выкрутиться
-
Попробуй при дисконнекте или ошибке отсылать сообщение постом и делать ФРИ для твоего TelnetSocket, а при новом коннекте заново КРЕАТИТЬ :))) Думаю в твоем случае это подойдет!!! Конечно можно переписать на сокетах, тогда таких глюков не будет. Тем более что тебе для эмитации телнета не блок режим не обязателен...
-
Вот один из наиболее простых вариантов преодоления засады: procedure TForm1.ClientOnError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
var
sa: TSockAddrIn;
len: Integer;
begin
...
if (ErrorEvent = eeConnect) and (ErrorCode = WSAEADDRNOTAVAIL) then
begin
GetSockName(Socket.SocketHandle, sa, len);
if sa.sin_addr.S_addr = INADDR_ANY then
следует повторить попытку асинхронного коннекта к ЭТОМУ же хосту, теперь она не вызовет отказ с кодом 10049
end;
...
end;
-
То Сергей М.: Приветствую! Не получилось - в строке
if sa.sin_addr.S_addr = INADDR_ANY then
sa.sin_addr.S_addr не равен INADDR_ANY...
|