-
Доброго всем времени. При работе с чистыми сокетами заметил для себя неожиданность: Error:='';
if OpenDataPort then begin
Answer:=SendCommand('LIST '+APath,true);
Sleep(100);
ReadAll(SocketDataHandle);
CloseDataPort;
Answer:=AsString;
if Error<>'' then begin Result:=false;end
else Result:=true;
end else begin
Result:=false;
end; Фишка в том что если убрать Sleep(100); или поставить меньше то данные из порта данных не считываются. Вернее приходит одна строка Total 0Я не понимаю, это что так и должно быть - задержка перед считыванием данных?
-
Всякие Sleep() в коде - это костыли, которые рано или поздно подведут.
> Я не понимаю, это что так и должно быть - задержка перед > считыванием данных?
Ну ты что ожидал что тебе сервер немедленно ответит?
в ReadAll(SocketDataHandle); у тебя что написано то?
-
var buf:array[0..512] of byte;siz:ssize_t; rc:Integer;
begin
Clear;
Position:=0;
repeat
FillChar(buf,sizeof(buf),0);
siz:=fprecv(hand,@buf[0],sizeof(buf),0);
Write(buf,siz);
rc:=Size;
until (siz<=0)or(siz<sizeof(buf));
Result:=Size;
end; Короче считка. Write - метод TMemoryStream. Хорошо, сервер мне сразу не ответит, как можно узнать что данные на считывание готовы?
-
Можно конечно ioctrlsocket, select
-
Ясно. спс.
-
Не пойму почему данные не считываются даже если select() отвечает готовностью. Вот код проверки: var
fs:TFDSet;
begin
WSASetLastError(0);
FD_ZERO(fs);
FD_SET(sockHandle,fs);
Result:=select(0,@fs,nil,nil,nil);
if Result=-1 then begin
Result:=WSAGetLastError;
Error:=SysErrorMessage(Result);
end else begin
end;
end; sockHandle сокет, откуда пойдет считка. select() возвращает единицу, мол сокет готов для считывания, но сразу последующие за этим кодом recv() данные выдает не те что нужно. Sleep() хоть и костыль, но помогает. Всмысле показывает что считывание данных правильное - resv() после него данные выдает правильные. Я вообще правильно select() использую?
-
> Я вообще правильно select() использую?
неправильно
-
Как правильно? В чем моя ошибка?
-
> Виталий (06.11.13 11:50) [5]
Во-первых, ты не задал интервал, сколько хочешь ждать. Во-вторых, надо проверять множества, как то так будет: function CanRead(ASocket: TSocket): boolean;
var
fdset: TFDSet;
tv: TTimeVal;
begin
tv.tv_sec := 0; tv.tv_usec := 0;
FD_ZERO(fdset);
FD_SET(ASocket, fdset);
if select(1, @fdset, nil, nil, @tv) = SOCKET_ERROR Then
raise TSocketError.Create;
CanRead := FD_ISSET(ASocket, fdset);
end;
-
> Виталий (06.11.13 11:50) [5]
И после select-а не помешает выполнить ioctlsocket(ASocket, FIONREAD, TotalBytesToRead), чтобы узнать сколько у нас там байт готово для чтения в TotalBytesToRead.
И все это хозяйство select и ioctlsocket надо вызывать в цикле пока не окажется, что данных больше нету для считывания, тогда мы берем все что считали и смотрим это все или нет.
-
> пока не окажется, что данных больше нету для считывания
Т.е. нужно совместить recv и эти функции в цикле считывания? Сначала Select() узнаем готовность сокета, потом ioctlsocket - узнаем сколько считать, и сразу же recv для считывания?
-
> ты не задал интервал
И не нужно. Так и задумано - ждать до посинения в моем случае.
> надо проверять множества
Для чего?
-
> Сначала Select() узнаем готовность сокета, потом ioctlsocket > - узнаем сколько считать, и сразу же recv для считывания? >
да
> Для чего?
то что select не вернула SOCKET_ERROR еще не означает вообще говоря, что сокет доступен для чтения
-
> Виталий (06.11.13 14:07) [11]
> И не нужно. Так и задумано - ждать до посинения в моем случае.
И повиснешь если сервер вообще не ответит. Лучше все же поставь интервал.
-
Ладно интервал я поставлю. Не в нем вопрос.
> еще не означает вообще говоря, что сокет доступен для чтения
Так как определить поступили ли данные для чтения или нет? ioctlsocket если я правильно понимаю всего лишь показывает сколько уже готово. Как мне определить достоверность поступления данных? На данный момент я от FTP сервера получаю фразу total 0 на команду LIST. Если ставлю Sleep() то помимо total 0 получаю еще и список файлов из каталога. Что получается? что сервер сначала пишет что-то в сокет, потом происходит проход по каталогу и возврат (дописывание) в сокет данных по файлам. так?
Если так то как мне понять что сервер выслал все данные?
-
> Если так то как мне понять что сервер выслал все данные?
Тебе сервер в канал управления должен сказать
-
А-а-а... Не трогать данные, пока не придет ответ на саму команду? А потом уже либо считывать либо анализировать ошибку, верно?
|