![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Recv и синхронный режим [D5]
Ivan K © (2004-06-14 15:09:00)Как узнать, пуст ли буфер? А то иначе при вызове Recv оно (в смысле Recv) ждет, пока в нем что-то будет и вешает прогу...
Verg (2004-06-17 11:01:00) [21]
> Если вместо
> if ioctlsocket(Cs, FIONREAD, bytes_in_buffer) <> SOCKET_ERROR
> then
> C := Recv(Cs, A, bytes_in_buffer, 0);
> я пишу просто
> C := Recv(Cs, A, 1024, 0);
> то в А записывается массив данных...
> Это не показатель?
Показатель чего? Ты чего хочешь добиться-то?
> C := Recv(Cs, A, 1024, 0); то в А записывается массив данных...
Конечно. recv-то c 1024 будет ждать, пока данные в сокете появятся, хоть сколько данных, хоть один байт.
По шагам:
if ioctlsocket(Cs, FIONREAD, bytes_in_buffer) <> SOCKET_ERROR then
Теперь bytes_in_buffer содержит кол-во байтов, которе на данный моментпринял сокет со времени последнего recv. Эта-то ф-ция ничего не ждет. Она немедленно возвращает запрошенную информацию о состоянии буфера приема.
if ioctlsocket(Cs, FIONREAD, bytes_in_buffer) <> SOCKET_ERROR then
begin
if bytess_in_buffer > 0 then
C := Recv(Cs, A, bytes_in_buffer, 0); // Тут понятно
else
// А тут что ты намерен делать? Что дальше-то?
end;
Digitman (2004-06-17 09:22:00) [22]
> Ivan K (17.06.04 01:16) [13]
> У Socket_ERROR код 0... Там чуть ниже условие С > 0
> Если вы об этом...
Нет, не об этом.
Какое отношение "чуть ниже условие С > 0" имеет к вызову ФУНКЦИИ(!!) Send() ? Ведь эта функция возвращает результат ! И этот результат отражает успешность или неуспешность выполнения ф-ции ..А ты его, этот результат, игнорируешь, вызывая ф-цию как процедуру и считая, очевидно, что send() всегда выполнится успешно ..
> эээ... опиши что?..
> от почтового сервера в ответ на top 1 0 (что и передается
> Send(Cs, A, Length(S), 0) ) приходит
> +ОК#13#10
это и есть фрагмент протокола инф.обмена между сервером и клиентом - в ответ на запрос предопределенного формата/содержания приходит ответ также предопределенного (для ДАННОГО запроса) формата/содержания
> Остальное в след. запрос принимается
да ничего подобного ! в ответ на 'top 1 0' сервер не ждет, пока ты сподобишься прочитать '+OK', он посылает поточныеданные, начинающиеся с '+OK'
затребовав для чтения при первом Recv() 1000 байт, ты можешь получить заранее неизвестное (в диапазоне от 0 до 1000) число инф.байт ответного потока.. среди полученных в этот момент байт может оказаться не только '+OK', но и некоторая часть данных, которые сервер немедленно посылает следом за '+OK'
теперь - по поводу ioctlsocket(socket, FIONREAD, bytes_in_buffer) ...
не обольщайся, что даже если в bytes_in_buffer будет возращено ненулевое значение, например bytes_in_buffer = 15, то последующим recv() ты прочитаешь ровно 15 байт - это вовсе не гарантируется ... в дан.случае bytes_in_buffer показывает тебе, к приему не более какогочисла байт ты должен быть готов
Ivan K (2004-06-17 02:18:00) [23]>Я не вижу в твоем коде отражения твоего понимания. Т.е. - откуда ж такая уверенность, что в буфере "что-то ведь" есть? :)
постараюсь... %)
Если вместо
if ioctlsocket(Cs, FIONREAD, bytes_in_buffer) <> SOCKET_ERROR then
C := Recv(Cs, A, bytes_in_buffer, 0);
я пишу просто
C := Recv(Cs, A, 1024, 0);
то в Азаписывается массив данных...
Это не показатель?
По поводу каши в голове... да, похоже у меня тоже заваривается...%))
Но от почтового сервера в ответ на top 1 0(что и передается Send(Cs, A, Length(S), 0) ) приходит
+ОК#13#10
и позже заголовок письма... Я так понял, его надо считывать следующим Recv'ом...
Опять непонятно объяснил?%)
Verg (2004-06-17 01:37:00) [24]
> Дык в том-то и дело, что bytes_in_buffer = 0. А в буфере
> все же что-то ведь есть!
Я не вижу в твоем коде отражения твоего понимания. Т.е. - откуда ж такая уверенность, что в буфере "что-то ведь" есть? :)
Про какой вообще тогда "буфер" идет речь? - Сформулируй.
> А там кроме первого знака "+" есть еще ОК#13#10. И всё.
> Остальное в след. запрос принимается. Хотя теперь есть сомнение,
> на хорошем канале в один буфер всё не сольется ли?..
/*
"Полная каша в голове" (С) Digitman
*/
:))
Ivan K (2004-06-17 01:16:00) [25]2 Digitman
> > Send(Cs, A, Length(S), 0);
>
>
> где анализ результата ?
У Socket_ERROR код 0... Там чуть ниже условие С > 0
Если вы об этом...
> > C := Recv(Cs, A, 1000, 0);
>
>
> а это что такое ? почему именно 1000 ?
А почему бы нет? А сколько? Как узнать размер принятой информации? Про ioctlsocket узнал из этого топика, да и сним пока ничего не получилось... Затем и пишу сюда за помощью...
> ты же следом затираешь содержимое буфера А новыми принимаемыми
> данными, даже не удосужившись обработать уже принятые в
> буфер данные (кроме первого символа "плюс")
А там кроме первого знака "+" есть еще ОК#13#10. И всё. Остальное в след. запрос принимается. Хотя теперь есть сомнение, на хорошем канале в один буфер всё не сольется ли?..
Область для меня новая, а потому не всё могу объяснить...
> опиши свой прикладной протокол инф.обмена ..
эээ... опиши что?.. %)) /я не волшебник - я только учусь =)
Ivan K (2004-06-17 01:04:00) [26]
> можно не очень сложно определить путем математического сравнения
> этого количества байтов (bytes_in_buffer) со специальной
> величиной, в народе прозванной НУЛЕМ
Дык в том-то и дело, что bytes_in_buffer = 0. А в буфере все же что-то ведь есть!
Просто после подсказки пользовать такую удобную функцию моя цель несколько изменилась:
Раз можно точно узнать, сколько точно байтов в буфере, то зачем считывать всё блоками и проверять на 0? Лучше сразу получить весь буфер целиком, что я и попытался проделать в вышеописанном коде.
/я наверное не могу точно сформулировать, что хочу и что получаю... всё больше путаюсь%)
Verg (2004-06-16 18:45:00) [27]Еще раз сначала.
Ты спрашиваешь:
> Ivan K (14.06.04 15:09)
> Как узнать, пуст ли буфер?А то иначе при вызове Recv оно
> (в смысле Recv) ждет, пока в нем что-то будет и вешает прогу...
Я отвечаю.
Вот как узнать количество байтов в приемном буфере сокета:
>
>
> Verg © (14.06.04 15:26) [1]
> var
> bytes_in_buffer : integer;
> ................
> if ioctlsocket(socket, FIONREAD, bytes_in_buffer) <> SOCKET_ERROR
> then
> begin
> bytes_in_buffer - содержит количество байтов в приемном
> буфере
> сокета socket
> end;
> ...............
Какие "еще" советы нужны?
Если ты знаешь количество байтов в приемном буфере сокета, то пуст он или не пуст можно не очень сложно определить путем математического сравнения этого количества байтов (bytes_in_buffer) со специальной величиной, в народе прозванной НУЛЕМ. :))
Verg (2004-06-16 18:38:00) [28]
> if ioctlsocket(Cs, FIONREAD, bytes_in_buffer) <> SOCKET_ERROR
> then
> C := Recv(Cs, A, bytes_in_buffer, 0); - ваш совет
Чего "ваш совет"? Не понял.
Digitman (2004-06-16 16:46:00) [29]
> Send(Cs, A, Length(S), 0);
где анализ результата ?
> C := Recv(Cs, A, 1000, 0);
а это что такое ? почему именно 1000 ?
ты же следом затираешь содержимое буфера А новыми принимаемыми данными, даже не удосужившись обработать уже принятые в буфер данные (кроме первого символа "плюс")
> ваш совет
до "совета" тут как до Китая еще ...
опиши свой прикладной протокол инф.обмена ..
Ivan K (2004-06-16 16:04:00) [30]
var
Cs : TSocket;
C : integer;
S : string;
A : array[0..2048] of Char;
bytes_in_buffer : integer;
begin
...
S := 'top '+ IntToStr(Num) + ' 0'#13#10;
StrPCopy(A, S); // перевод строки в Char
bytes_in_buffer := 0;
Send(Cs, A, Length(S), 0);
C := Recv(Cs, A, 1000, 0);
if (C > 0) and (A[0] = '+') then
if ioctlsocket(Cs, FIONREAD, bytes_in_buffer) <> SOCKET_ERROR then
C := Recv(Cs, A, bytes_in_buffer, 0); - ваш совет
if (C > 0) then
begin
...
end;
Если вместо жирного написать
C := Recv(Cs, A, 1024, 0)
то буфер забивается своими 1024мя символами (или меньше, если меньше=) ).
Единственная проблема, что он числа 1024 может не хватить, а выделять больше тоже не хочется, ибо нефиг память переводить ;)
Verg (2004-06-16 13:48:00) [31]
> Ivan K (15.06.04 23:24) [5]
Покажи полный код участка приема. Как и где ты применяешь эти ф-ции.
Digitman (2004-06-16 08:12:00) [32]
> ждет, пока в нем что-то будет и вешает прогу
либо выноси работу с гнездом в доп.код.поток либо используй неблокирующий режим работы гнезда
Ivan K (2004-06-15 23:24:00) [33]хм.. Как же правильно "дождаться" того момента, чтобы точно знать, что данные на месте?
И еще...
C := Recv(Cs, A, 1024, 0)писалось не после, а вместоусловия с ioctlsocket. Так почему в Recv данные дошли, а в Iocltsocket - нет?? /непонятненько%(
Verg (2004-06-14 18:58:00) [34]
> C := Recv(Cs, A, 1024, 0);
> он возвращает мне данные..
Значит на момент вызова ioctlsocket данных еще не было, а на момент recv - были. Вот и все.
Ivan K (2004-06-14 16:33:00) [35]ой... сия конструкция мне ноль возвращает в bytes_in_buffer. хотя когда в тупую ставлю
C := Recv(Cs, A, 1024, 0);
он возвращает мне данные..
Ivan K (2004-06-14 16:15:00) [36]спасибо.
Verg (2004-06-14 15:26:00) [37]
var
bytes_in_buffer : integer;
................
if ioctlsocket(socket, FIONREAD, bytes_in_buffer) <> SOCKET_ERROR then
begin
bytes_in_buffer - содержит количество байтов в приемном буфере
сокета socket
end;
...............