Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Recv и синхронный режим [D5]


Страницы:   1 2

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;
...............


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо