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

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

Не возвращается количество полученных байт в блокирующисокетах??? [D6, Win2k]


Страницы:   1 2 3

slgeo ©   (2004-03-19 10:04:00) 

У меня идет обмен по блокирующим сокетам, а точнее передача файла от
серверного потока клиентскому:
на клиенте срабатывает следующий код
   var
    Buf : string;
   
   if Stream.WaitForData(40000) then
     begin
       SetLength(Buf, 18);
       nRead := Stream.Read(Buf[1], 18);
   ...
   end;
   
    Так вот на некоторых машинах, точнее на 2-х из 5-ти, в nRead
    возвращается 0! Но данные на самом деле передаются! На этих 2-х
    установлена Win98 SE, на остальных 3-х машинах, где в nRead
    возвращается количество принятых байт:
    1 - WinXP
    2 - WinXP
    3 - Win98 SE

   Я уже не знаю где искать, замена файлов
   winsock.dll,wsock32.dll,wininet.dll ни к чему не приводит.


Verg   (2004-03-19 20:58:00) [1]

Мылом присылай :)

А зарегистрироавтья? Кто ты и откуда, парень? Давноль живешь?


slgeo   (2004-03-19 20:49:00) [2]

переустановка ОС не входит в планы (клиенты злые и неотзывчивые намечаются, причем территориально достаточно удаленные), поэтому обйдемся пока recv. Еще раз будем знать, что надо поглубже с исходники забираться.

Спасибо Verg и Digitman за то что поделились опытом, теперь и у нас что-нибудь останется

Пиво куда приносить??? :)


Verg   (2004-03-19 20:26:00) [3]

Не знаю. Лучший способ - переустановить винды полностью. Со всеми сериспаками, так как оба способа (recv, ReadFile) работают нормально и абсолютно безглючно.

Не забудь, однако, про [17],[18] и прочие посты - это ОЧЕНЬ важно, и о совершенно "в десятку" замечаниях и оценках Digitman-а.
В следующий раз попробуй не "лезть в бутылку".


slgeo   (2004-03-19 19:31:00) [4]

Я даже kernel32.dll менял, где эта долбанная функция ReadFile, все равно никакой реакции, те же глюки


slgeo   (2004-03-19 19:27:00) [5]

>Verg
через recv пишет
------- Disconnected bytes received---: 51603
через ReadFile пишет
------- Disconnected bytes received---: 0

Что и требовалось доказать!
Только посоветуйте как быть,пожалуйста,с меня много-много пива :)
Переделывать все на recv?


Digitman   (2004-03-19 18:47:00) [6]


> slgeo


все твои беды  - от неумения грамотно построить алгоритм для конкретных условий и ПИО

вот псевдокод, который НАМНОГО упрощает и воспритие кода и его отладку :

procedure TSomeTransportThread.Execute;
begin
 Transport := CreateTransport;
 try
  Requestparams := GetRequestParams(..);
  Context := SendRequest(Transport, Requestparams);
  Response := ReceiveResponse(Transport, Context);
 finally
   Transport := nil;
 exit;
end;


Verg   (2004-03-19 18:44:00) [7]

Вот тут кусочек от клиента HTTP-шного.
Упростил все "до дуры" - попробуй запустить на "плохой" машинке.
IP адрес, порт и текст запроса по-месту изменишь на какой нужно.

Там два режима приема - через ReadFile и через recv. Попробуй оба.

Что скажет?

program Client;
{$APPTYPE CONSOLE}

uses
 Windows,
 WinSock,
 SysUtils,
 SyncObjs;

var A : TSockAddrIn;
   S : TSocket;
   WSAData : TWSAData;
   Ret : integer;
   Buffer : array[0..255] of char;
   Ostr : string;
   FEvent : TEvent;
   RecvSize : DWORD;

function ToOem(const S : string):string;
begin
 Result := S;
 CharToOemBuff(pchar(Result), pchar(Result), length(Result));
end;

procedure PrintErr(Err : DWORD);
begin
 Writeln(ToOem(SysErrorMessage(Err)));
end;

function checksocket(Ret : integer):boolean;
begin
 Result := Ret = SOCKET_ERROR;
 if Result then
 begin
   PrintErr(Ret);
   Readln;
 end;
end;

function Receive_Mode1: integer;
begin
 result := recv(S, Buffer, sizeof(buffer), 0);
end;

function Receive_Mode2: integer;
var
 Overlapped: TOverlapped;
begin
 FillChar(OVerlapped, SizeOf(Overlapped), 0);
 Overlapped.hEvent := FEvent.Handle;
 if not ReadFile(S, Buffer, sizeof(buffer), DWORD(Result),
    @Overlapped) and (GetLastError <> ERROR_IO_PENDING) then
 begin
   Writeln;
   PrintErr( GetLastError );
   Result := SOCKET_ERROR;
 end else
 if FEvent.WaitFor(INFINITE) <> wrSignaled then
 else begin
   GetOverlappedResult(S, Overlapped, DWORD(Result), False);
   FEvent.ResetEvent;
 end;
end;

begin
 Ret := WSAStartup(MAKEWORD(1,1), WSAData);
 if  Ret = NO_ERROR then
 try
   FEvent := TEvent.Create(nil, true, false, '');
   S := socket(PF_INET, SOCK_STREAM, 0);
   if S = INVALID_SOCKET then
   begin
     PrintErr(WSAGetLastError);
     readln;
     exit;
   end;
   try
     FillChar(A, sizeof(A), 0);
     A.sin_family := AF_INET;
     A.sin_port   := htons( 80 );
     A.sin_addr.S_addr := inet_addr('194.67.57.51');
     if checksocket(connect(S, A, sizeof(A))) then
       exit;
     Ostr := 'GET / HTTP/1.0'#13#10#13#10;
     if checksocket(send(S, Ostr[1], length(Ostr), 0)) then
       exit;
     RecvSize := 0;
     repeat
       Ret := Receive_Mode2;
       if checksocket(Ret) then
         exit;
       if Ret = 0 then
       begin
         Writeln;
         WriteLn('------- Disconnected bytes received---:', RecvSize);
         readln;
         exit;
       end;
       Inc(RecvSize, Ret);
       SetString(Ostr, Buffer, Ret);
       Write(ToOem(OStr));
     until false;
   finally
     closesocket(S);
   end;
 finally
   WSACleanup;
   FEvent.Free;
 end else
 begin
   PrintErr(Ret);
   readln;
 end;
end.


slgeo   (2004-03-19 18:05:00) [8]

Обычный TCP/IP. Работает аська, инет через вингейт, работает вся сеть... в этой сети на двух машинах прога работает, на трех не работает...


Verg   (2004-03-19 17:46:00) [9]

NetBEUI?


slgeo   (2004-03-19 17:29:00) [10]

Минутку... если повреждены драйвера, сеть будет работать?


Verg   (2004-03-19 17:11:00) [11]


> function GetOverlappedResult; external kernel32 name 'GetOverlappedResult';


А что на это должны сказать?
Функция такая из kernel32. Возвращает результат выполнения Overlapped IO.

Если ф-ция WaitFor возвращает Signaled, а кол-во принятых байт равно нулю, то это значит, что соединение было закрыто.

Все, и не только это бесчисленное число раз проверялось и не только мной (нами), но и тысячами работоспособных программ.


> Почему, при соблюдении правил программирования, как основных
> так и не очень, прога работает на одном железе и не работает
> на другом?


Я уже тебе говорил выше [17],[18], что процедура приема сделана неверно.


>        SetLength(Buf, 18);
>        nRead := Stream.Read(Buf[1], 18);
> //      SetLength(Buf, nRead); если убрать комментарий то
> Buf очищается        
>        if POS('UPDATE!',Buf)=1  then
>        begin


И здесь тоже неверно. Кто тебе обещал, что Read примет всю заголовочную строку за раз?

Все это, конечно, справедливо если драйвера TCP/IP не повреждены.


Digitman   (2004-03-19 17:11:00) [12]


> а что вы на это скажете?:


для начала я скажу, что твой исх.текст, реализующий алгоритм транспорта  - большая каша ..


slgeo   (2004-03-19 16:55:00) [13]

> Digitman
А то что я выяснил что возвращает функция хочешь сказать мне винда вывалила большими буквами на синем экране?

То что чешу репу уже третий день и только после долгих и бесполезных действий обратился за помощью в форум, а кроме
споров двух, "имеющих колоссальный практ. им теор. опыт" админов я не увидел... то, о чем вы спорили, перепробовано в течение месяца согласно правилам камасутры и Билла...
   Вопрос был следующим... Кратко...
Почему, при соблюдении правил программирования, как основных так и не очень, прога работает на одном железе и не работает на другом?
   Это ИЗ-ЗА ЖЕЛЕЗА, Винды (имеется в виду SP) или же моих кривых рук, которые уже написали довольно боьшое кол-во софта на Делфи...
   Перед тем как обвинять кого-то в некомпетентности есть смысл проверить... Вы проверяли? На Винде с первым и вторым сервис паком? нет? так я и думал...
а что вы на это скажете?:
function GetOverlappedResult; external kernel32 name 'GetOverlappedResult';


Digitman   (2004-03-19 16:36:00) [14]


> slgeo


слухай сюда ...

при всем моем уважении к тебе, искренне пытающегося найти "первопричину", и к Андрею, искренне пытающегося наставить тебя на путь истинный (имея на о колоссальный практ. им теор. опыт), репу свою чесать по поводу "глюков" должен, в 1-ю очередь, именно ТЫ, и никто иной  ...

и у тепя, мил мой, коль скоро ты пользуешь Делфи, под рукой всегда есть великолепный инструмент под названием Интегрированный Отладчик Делфи ... и какого шута ты им не пользуешься по сей момент - это для нас с Андреем и коллегами составляет великую гостайну ... в каковую (в тайности применения которого в поисках истины) без твоего высочайшего соизволения мы не имеем возможности "въехать"


Digitman   (2004-03-19 16:36:00) [15]


> slgeo


слухай сюда ...

при всем моем уважении к тебе, искренне пытающегося найти "первопричину", и к Андрею, искренне пытающегося наставить тебя на путь истинный (имея на о колоссальный практ. им теор. опыт), репу свою чесать по поводу "глюков" должен, в 1-ю очередь, именно ТЫ, и никто иной  ...

и у тепя, мил мой, коль скоро ты пользуешь Делфи, под рукой всегда есть великолепный инструмент под названием Интегрированный Отладчик Делфи ... и какого шута ты им не пользуешься по сей момент - это для нас с Андреем и коллегами составляет великую гостайну ... в каковую (в тайности применения которого в поисках истины) без твоего высочайшего соизволения мы не имеем возможности "въехать"


Digitman   (2004-03-19 16:35:00) [16]


> slgeo


слухай сюда ...

при всем моем уважении к тебе, искренне пытающегося найти "первопричину", и к Андрею, искренне пытающегося наставить тебя на путь истинный (имея на о колоссальный практ. им теор. опыт), репу свою чесать по поводу "глюков" должен, в 1-ю очередь, именно ТЫ, и никто иной  ...

и у тепя, мил мой, коль скоро ты пользуешь Делфи, под рукой всегда есть великолепный инструмент под названием Интегрированный Отладчик Делфи ... и какого шута ты им не пользуешься по сей момент - это для нас с Андреем и коллегами составляет великую гостайну ... в каковую (в тайности применения которого в поисках истины) без твоего высочайшего соизволения мы не имеем возможности "въехать"


slgeo   (2004-03-19 16:29:00) [17]

проверил
FEvent.WaitFor(FTimeOut) возвращает wrSignaled !


Verg   (2004-03-19 15:28:00) [18]

Еще раз говорю - значит сервер закрывает соединение (завершает клиентский поток). Возможно он неверно принимает запрос. Ищи там. Пусть сервер ведет лог.

Провеь настройки TCP/IP на "неработающей" машине.

Далее. Проверить надо что именно возвращает

   if FEvent.WaitFor(FTimeOut) <> wrSignaledthen
     Result := 0
   else

Если он возвращает не wrSignaled, то тут варанты:
 TWaitResult = (wrSignaled, wrTimeout, wrAbandoned, wrError);

Если этого сделать не сможешь, то просто замени прием на
с nRead := Stream.Read(Buf[1], 18);
на

if Stream.WaitForData(30000) then
 nRead := recv(ClientSocket.SocketHandle, buf[1], length(buf), 0);
else
 nRead := SOCKET_ERROR-1;

Посмотри что скажет.


slgeo   (2004-03-19 14:39:00) [19]

вот практически вся процедура принимающей стороны
procedure OptClientThread.Execute;
var
 I, nRead: Integer;
 Stream: TWinSocketStream;
 ms : TMemoryStream;
 Buf, StrIn : String;
 fsize : integer;
 strFile : string;
 FileSize : integer;
begin
 try
   ClientSocket := TClientSocket.Create (nil);
   Stream := nil;
   try
     ClientSocket.Address := ServerAddress;
     ClientSocket.ClientType := ctBlocking;
     ClientSocket.Port := RemotePort;
     ClientSocket.Active := True;
     Stream := TWinSocketStream.Create(ClientSocket.Socket, 30000);
   except
     FLogMsg := 'Нет соединения с сервером! Повторите обновление позднее!';
     Synchronize(DoLog);
     Exit;
   end;
     FLogMsg := 'Отправляем запрос на обновление...';
     Synchronize(DoLog);
     dmData.IBSQL.Close;
     dmData.IBSQL.SQL.Text := 'select sendstatus from settings';
     dmData.IBSQL.ExecQuery;
     ClientSocket.Socket.SendText ('UPD_'+IntToStr(UIN)+'_'+dmData.IBSQL.Fields[0].AsString+'!');
     if Stream.WaitForData(50000) then
     begin
       Buf := '';
       SetLength(Buf, 18);
       nRead := Stream.Read(Buf[1], 18);
//      SetLength(Buf, nRead); если убрать комментарий то Buf очищается       
       if POS('UPDATE!',Buf)=1  then
       begin
          ssize := Copy (Buf, 8, 10);
          try
            fsize := StrToInt(ssize);
          except
            fsize := 0;
          end;
       end
     end else
         begin
           FLogMsg := 'Нет ответа на запрос обновления!!!';
           Synchronize(DoLog);
           Exit;
         end;

     //получение пакета обновления
    DeleteFile(ExtractFilePath(Application.ExeName)+'update.txt');
    ms := TMemoryStream.Create;
    FLogMsg := 'Загружаем данные...';
    if Stream.WaitForData(60000) then
     begin
       Buf := '';
       SetLength(Buf, 256);
       FMaxProgress := fsize;
       Synchronize(DoMaxProgress);
       while True do
       begin
         nRead := Stream.Read(Buf[1],256);
         if Pos('000000!',Buf)>0 then
         begin
           StrIn := Copy(Buffer,1,Pos('000000!',Buf)-1);
           ms.Write (strIn[1], Length(strIn));
           FMaxProgress := 0;
           Synchronize(DoMaxProgress);
           Break;
         end
         else
         begin
           ms.Write(Buf[1], nRead);
           FProgress := nRead;
           Synchronize(DoProgress);
         end;
       end;
     end else
         begin
           FLogMsg := 'Не получен очередной пакет обновления!!!';
           Synchronize(DoLog);
           Exit;
         end;
     FLogMsg := 'Загрузка завершена!!!';
     Synchronize(DoLog);
     ms.Position := 0;
     ms.SaveToFile(ExtractFilePath(Application.ExeName)+'inbox\'+'update.zip');
     ms.Free;
    .....
 except
    ....
 end;
end;


Verg   (2004-03-19 14:25:00) [20]


> [35] slgeo   (19.03.04 14:13)


В обработчике чего? Ну и что, что "первый"?

Слушай, ну сколько можно из тебя "клещами"-то все вытаскивать?

Read всегда возвращает истинное положение дел в сокете.
Если он сказал, что ноль байтов принял, значит так оно и есть.
Не веришь?

Я проверял многократно (мягко говоря:) ) - все так и есть.

Если у тебя порежденный драйвер TCP/IP на машине, то это должно сказаться и на других приложениях, работающих через сокеты (через WinSock).


Страницы:   1 2 3

Наверх

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