![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
событие TTcpClient.OnConnect [D7, XP]
_Андрей © (2009-04-24 09:45:00)Здравствуйте, пытаюсь через сокеты подсоединиться к FTP, использую TTcpClient с закладки Internet. Делаю так:
procedure TForm1.Button1Click(Sender: TObject);
begin
TcpClient.LocalHost := '127.0.0.1';
TcpClient.LocalPort := '4567';
TcpClient.Connect
end;
procedure TForm1.TcpClientError(Sender: TObject; SocketError: Integer);
begin
MessageBox(handle, PChar(Format('Error [%d]', [SocketError])), PChar ('Socket'), MB_OK or MB_ICONERROR)
end;
procedure TForm1.TcpClientConnect(Sender: TObject);
begin
MessageBox(handle, PChar('Connect!'), PChar('Socket'),
MB_OK or MB_ICONINFORMATION)
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if TcpClient.Connected then TcpClient.Disconnect
end;
В неблокирующем режиме коннектится (и вызывается событие TTcpClient.OnConnect), в блокирующем выдаёт ошибку "10035", прочёл что это "не совсем ошибка", а скорее сообщение говорящее о том что операция не может быть выполнена немедленно. "Ок, как скажете...". Непонятно же почему не вызывается событие TTcpClient.OnConnect, то есть непонятно как же мне узнать о факте соединения... подскажите, плиз, как быть...
Сергей М. (2009-04-24 15:09:00) [1]
> откуда ж тогда он это брал, с "прошлых коннектов" сокета?
Зачем ? С этого коннекта и взял - сервер-то не молчит.. Сразу после коннекта сервер представился, по всем, тэкскэть, канонам FTP)..
Я тут немного "затормозил" - упустил из виду, что речь идет конкретно об FTP.
Т.е. о частномслучае, в котором WaitForData м.б. в принципе использован для обнаружения факта состоявшегося коннекта.
А в общемслучае WaitForData для этой цели неприменим по причине [6]
_Андрей (2009-04-24 15:01:00) [2]хм... после такого "коннекта" я вызывал Receiveln и он мне выдавал что-то типа: "220 FTP server ready и т.д.", откуда ж тогда он это брал, с "прошлых коннектов" сокета?
Сергей М. (2009-04-24 14:39:00) [3]
> имею ввиду его использование вместо Select
Не получится.
WaitForData не может отследить факт подключения, если партнер по соединению будет молчать.
_Андрей (2009-04-24 13:40:00) [4]Я имею ввиду его использование вместо Select
function TBaseSocket.WaitForData(TimeOut: Integer): Boolean;
var
ReadReady, ExceptFlag: Boolean;
c: Char;
begin
Result := False;
// Select also returns True when connection is broken.
if Select(@ReadReady, nil, @ExceptFlag, TimeOut) then
Result := ReadReady and not ExceptFlag and
(PeekBuf(c, sizeof(c)) = 1);
end;
Сергей М. (2009-04-24 11:55:00) [5]
> остановился пока на использовании TcpClient.WaitWaitForData
К коннектув каком бы то ни было режиме этот метод неимеет отношения.
_Андрей (2009-04-24 11:02:00) [6]Да, касательно коннекта это работает, спасибо большое, ни в жизнь бы не догадался (только я остановился пока на использовании TcpClient.WaitWaitForData, более читабельный вид всё-таки)
_Андрей (2009-04-24 10:37:00) [7]
> Ты ничего не перепутал ?
Да-да, разумеется "в неблокирующем", ошибся, извините...
По поводу TTcpClient.Handle сейчас попробую, спасибо!
Сергей М. (2009-04-24 10:32:00) [8]
> в блокирующем выдаёт ошибку "10035"
Ты ничего не перепутал ?
Такая ошибка может возникнуть именно в неблокирующем режиме, поскольку ф-ция winsock.connect в этом режиме запускает асинхроннуюоперацию коннекта, о чем собссно и информирует код ошибки WSAEWOULDBLOCK=10035.
Вот цитата из "генофонда" c комментариями:
procedure TCustomIpClient.Open;
var
addr: TSockAddr;
begin
inherited Open;
if Active and not FConnected then
begin
addr := GetSocketAddr(FRemoteHost, FRemotePort);
..
FConnected := ErrorCheck(WinSock.connect(FSocket, addr, sizeof(addr))) = 0;
..
if FConnected then
DoConnect; //здесь вызывается обработчик события OnConnect, если он назначен
end;
end;
> как же мне узнать о факте соединения
В блокирующем режиме о факте успешного коннета сообщит либо True-результат вызова ф-ции Connect либо факт вызова обработчика OnConnect
В неблокирующем режиме в этом компоненте все сложнее.
По факту возникновения события OnError с кодом отказа WSAEWOULDBLOCK следует имея хэндл гнезда (см. TTcpClient.Handle) вызывать циклически ф-цию select(), которая рано или поздно сообщит о факте успешного (параметр writefds) или неуспешного (параметр exceptfds) коннекта.