Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2004.04.11;
Скачать: [xml.tar.bz2];

Вниз

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

 
slgeo   (2004-03-19 10:04) [0]

У меня идет обмен по блокирующим сокетам, а точнее передача файла от
серверного потока клиентскому:
на клиенте срабатывает следующий код
   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 ни к чему не приводит.


 
slgeo   (2004-03-19 10:04) [0]

У меня идет обмен по блокирующим сокетам, а точнее передача файла от
серверного потока клиентскому:
на клиенте срабатывает следующий код
   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 10:10) [1]

nRead =0 в данном случае означает, что соединение было закрыто.


 
Verg ©   (2004-03-19 10:10) [1]

nRead =0 в данном случае означает, что соединение было закрыто.


 
Digitman ©   (2004-03-19 10:12) [2]


> У меня идет обмен по блокирующим сокетам


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


 
Digitman ©   (2004-03-19 10:12) [2]


> У меня идет обмен по блокирующим сокетам


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


 
Digitman ©   (2004-03-19 10:15) [3]


> Verg ©   (19.03.04 10:10) [1]


уверен ?


   if FEvent.WaitFor(FTimeOut) <> wrSignaled then //нет данных в буфере приема
     Result := 0
   else
   begin
     GetOverlappedResult(FSocket.SocketHandle, Overlapped, DWORD(Result), False);
     FEvent.ResetEvent;
   end;


 
Digitman ©   (2004-03-19 10:15) [3]


> Verg ©   (19.03.04 10:10) [1]


уверен ?


   if FEvent.WaitFor(FTimeOut) <> wrSignaled then //нет данных в буфере приема
     Result := 0
   else
   begin
     GetOverlappedResult(FSocket.SocketHandle, Overlapped, DWORD(Result), False);
     FEvent.ResetEvent;
   end;


 
slgeo   (2004-03-19 10:19) [4]

to Digitman
с чего вдруг???
 OptClientThread = class(TThread)
 private
   ClientSocket: TClientSocket;
 ...
 end;

procedure OptClientThread.Execute;
var
 nRead: Integer;
 Stream: TWinSocketStream;  
 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
 ....
 end;


 
slgeo   (2004-03-19 10:19) [4]

to Digitman
с чего вдруг???
 OptClientThread = class(TThread)
 private
   ClientSocket: TClientSocket;
 ...
 end;

procedure OptClientThread.Execute;
var
 nRead: Integer;
 Stream: TWinSocketStream;  
 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
 ....
 end;


 
Verg ©   (2004-03-19 10:25) [5]

Если  это сработало (вернуло true)

>  if Stream.WaitForData(40000) then


значит в сокете сработал ReadFDS, а это в свою очередь означает, что у сокета во входном потоке что-то появилось. Это могут быть данные, а может быть и признак конца файла ( Read() вернет 0 )


> [2] Digitman ©   (19.03.04 10:12)


А с каким еще сокетом может работать TWinSocketStream, у которого есть метод WaitForData?


 
Verg ©   (2004-03-19 10:25) [5]

Если  это сработало (вернуло true)

>  if Stream.WaitForData(40000) then


значит в сокете сработал ReadFDS, а это в свою очередь означает, что у сокета во входном потоке что-то появилось. Это могут быть данные, а может быть и признак конца файла ( Read() вернет 0 )


> [2] Digitman ©   (19.03.04 10:12)


А с каким еще сокетом может работать TWinSocketStream, у которого есть метод WaitForData?


 
slgeo   (2004-03-19 10:32) [6]

>Verg

во-во это уже ближе, в Buf попадает что-то типа PK.... (если я не ошибаюсь это действительно признак конца файла). Но ведь с другой стороны был передан файл??? Куда он пропал?

Кстати выше по коду перед приемом файла у меня есть еще прием команды. Так вот в nRead снова 0, но в Buf данные попадают!!!


 
slgeo   (2004-03-19 10:32) [6]

>Verg

во-во это уже ближе, в Buf попадает что-то типа PK.... (если я не ошибаюсь это действительно признак конца файла). Но ведь с другой стороны был передан файл??? Куда он пропал?

Кстати выше по коду перед приемом файла у меня есть еще прием команды. Так вот в nRead снова 0, но в Buf данные попадают!!!


 
Digitman ©   (2004-03-19 10:36) [7]

при использовании TWinSocketStream.Read запускается асинхронная overlapped-операция ввода

блокирование вызывающего код.потока происходит здесь
 if FEvent.WaitFor(FTimeOut) <> wrSignaled then

а здесь - неблокирующая операция ввода
   if not ReadFile(FSocket.SocketHandle, Buffer, Count, DWORD(Result),
     @Overlapped) and (GetLastError <> ERROR_IO_PENDING) then
   begin
     ErrorCode := GetLastError;
     raise ESocketError.CreateResFmt(@sSocketIOError, [sSocketRead, ErrorCode,
       SysErrorMessage(ErrorCode)]);
   end;


 
Digitman ©   (2004-03-19 10:36) [7]

при использовании TWinSocketStream.Read запускается асинхронная overlapped-операция ввода

блокирование вызывающего код.потока происходит здесь
 if FEvent.WaitFor(FTimeOut) <> wrSignaled then

а здесь - неблокирующая операция ввода
   if not ReadFile(FSocket.SocketHandle, Buffer, Count, DWORD(Result),
     @Overlapped) and (GetLastError <> ERROR_IO_PENDING) then
   begin
     ErrorCode := GetLastError;
     raise ESocketError.CreateResFmt(@sSocketIOError, [sSocketRead, ErrorCode,
       SysErrorMessage(ErrorCode)]);
   end;


 
Verg ©   (2004-03-19 10:37) [8]

Я там не вижу никакого "приема файла". Я там вижу ожидание появления данных в сокете и попытку проичтать из него не более 18-ти байтов в строку.
Какой файл? Где файл?


 
Verg ©   (2004-03-19 10:37) [8]

Я там не вижу никакого "приема файла". Я там вижу ожидание появления данных в сокете и попытку проичтать из него не более 18-ти байтов в строку.
Какой файл? Где файл?


 
slgeo   (2004-03-19 10:43) [9]

вот так точнее
var
ms : TMemoryStream;

    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(Buf,1,Pos("000000!",Buf)-1);
           ms.Write (strIn[1], Length(strIn));
           FMaxProgress := 0;
           Synchronize(DoMaxProgress);
           Break;
         end
         else
           ms.Write(Buf[1], nRead);
       end;
     end else
         begin
           FLogMsg := "Не получен очередной пакет обновления!!!";
           Synchronize(DoLog);
           Exit;
         end;


 
slgeo   (2004-03-19 10:43) [9]

вот так точнее
var
ms : TMemoryStream;

    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(Buf,1,Pos("000000!",Buf)-1);
           ms.Write (strIn[1], Length(strIn));
           FMaxProgress := 0;
           Synchronize(DoMaxProgress);
           Break;
         end
         else
           ms.Write(Buf[1], nRead);
       end;
     end else
         begin
           FLogMsg := "Не получен очередной пакет обновления!!!";
           Synchronize(DoLog);
           Exit;
         end;


 
slgeo   (2004-03-19 10:44) [10]

и дальше естесвенно
     ms.Position := 0;
     ms.SaveToFile(ExtractFilePath(Application.ExeName)"+"update.txt");
     ms.Free;


 
slgeo   (2004-03-19 10:44) [10]

и дальше естесвенно
     ms.Position := 0;
     ms.SaveToFile(ExtractFilePath(Application.ExeName)"+"update.txt");
     ms.Free;


 
Digitman ©   (2004-03-19 10:52) [11]


> Verg ©   (19.03.04 10:25) [5]


да, я здесь был неточен

гнездо-то само по себе иниц-но для работы в блок.режиме, но работа с ним идет с использованием файлового overlapped-ввода/вывода, что само по себе подразумевает неблок.режим ввода/вывода


> slgeo


вот цитата :

The event specified in the OVERLAPPED structure is set to the signaled state upon completion of the read operation.

это означает, что сигнал ивента следует ожидать только ПОСЛЕ приема и доступности в файловом буфере тех самых запрошенных тобой 18-ти байт

если же ивент не просигналил за 30 секунд (ты сам обозначил это время), то, как видишь из исх.текста, метод Read вернет тебе 0 .. т.е. какая-то часть запрошенных к чтению данных успела прийти за это время, а какая-то еще "в пути"... очевидно, что следует циклически повторять вызов метода Read() до тех пор, пока не просигналит ивент либо не будет возбуждено исключение по потенциально возможному разрыву транспортного канала


 
Digitman ©   (2004-03-19 10:52) [11]


> Verg ©   (19.03.04 10:25) [5]


да, я здесь был неточен

гнездо-то само по себе иниц-но для работы в блок.режиме, но работа с ним идет с использованием файлового overlapped-ввода/вывода, что само по себе подразумевает неблок.режим ввода/вывода


> slgeo


вот цитата :

The event specified in the OVERLAPPED structure is set to the signaled state upon completion of the read operation.

это означает, что сигнал ивента следует ожидать только ПОСЛЕ приема и доступности в файловом буфере тех самых запрошенных тобой 18-ти байт

если же ивент не просигналил за 30 секунд (ты сам обозначил это время), то, как видишь из исх.текста, метод Read вернет тебе 0 .. т.е. какая-то часть запрошенных к чтению данных успела прийти за это время, а какая-то еще "в пути"... очевидно, что следует циклически повторять вызов метода Read() до тех пор, пока не просигналит ивент либо не будет возбуждено исключение по потенциально возможному разрыву транспортного канала


 
Verg ©   (2004-03-19 10:55) [12]

2 Digitman


>    if FEvent.WaitFor(FTimeOut) <> wrSignaled then //нет
> данных в буфере приема
>     Result := 0


Вот это есть некая "кривость". Потому как в результате невозможно отличить ситуацию таймаута от ситуации EOF (разрыв соединения собеседником).
Хоть бы -1 присвоили что-ли...

Сокет тем временем именно в блокирующем режиме. А для того, чтобы обеспечить возможность таймаута при чтении там воспользовались Overlapped IO с блокировкаой WaitForSingleObject (хотя можно было бы и select+recv-ом также все сделать).

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


 
Verg ©   (2004-03-19 10:55) [12]

2 Digitman


>    if FEvent.WaitFor(FTimeOut) <> wrSignaled then //нет
> данных в буфере приема
>     Result := 0


Вот это есть некая "кривость". Потому как в результате невозможно отличить ситуацию таймаута от ситуации EOF (разрыв соединения собеседником).
Хоть бы -1 присвоили что-ли...

Сокет тем временем именно в блокирующем режиме. А для того, чтобы обеспечить возможность таймаута при чтении там воспользовались Overlapped IO с блокировкаой WaitForSingleObject (хотя можно было бы и select+recv-ом также все сделать).

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


 
Verg ©   (2004-03-19 10:59) [13]


> успела прийти за это время, а какая-то еще "в пути"... очевидно,
> что следует циклически повторять вызов метода Read() до
> тех пор, пока не просигналит ивент либо не будет возбуждено
> исключение по потенциально возможному разрыву транспортного
> канала


Нет, ты забыл что ли, что waitfordata уже сработал, т.е. в приемном буфере сокета уже что-то должно быть - хоть данные, хоть EOF


 
Verg ©   (2004-03-19 10:59) [13]


> успела прийти за это время, а какая-то еще "в пути"... очевидно,
> что следует циклически повторять вызов метода Read() до
> тех пор, пока не просигналит ивент либо не будет возбуждено
> исключение по потенциально возможному разрыву транспортного
> канала


Нет, ты забыл что ли, что waitfordata уже сработал, т.е. в приемном буфере сокета уже что-то должно быть - хоть данные, хоть EOF


 
Digitman ©   (2004-03-19 11:11) [14]


> Verg ©   (19.03.04 10:59) [13]


а waitfordata-то здесь причем ? он не имеет отношения ни к overlapped-операции ввода ни к ивенту ..

ну да, ну вернул он True, что-то там в приехало ..

теперь мы стартуем/рестартуем собственно overlapped-операцию (неблокирующую по определению), после чего тут же анализируем сигнал ивента .. предположим, из запрошенных 18 байт на момент анализа ивента в файловом потоке ввода доступно всего 9 байт ... разумеется, ивент не просигналил еще ! ... а раз не просигналил, то и Result = 0...

ну и иная ситуация (та на которую ты намекаешь) - ивент просигналил, но в файловом потоке есть EOF ... тогда Read() вернет из overlapped-структуры то число байт, что находится в файловом потоке ДО Eof ... и вполне возможно, что до EOF ничего и не приходило ... тогда ситуация с Result = 0 так же объяснима


 
Digitman ©   (2004-03-19 11:11) [14]


> Verg ©   (19.03.04 10:59) [13]


а waitfordata-то здесь причем ? он не имеет отношения ни к overlapped-операции ввода ни к ивенту ..

ну да, ну вернул он True, что-то там в приехало ..

теперь мы стартуем/рестартуем собственно overlapped-операцию (неблокирующую по определению), после чего тут же анализируем сигнал ивента .. предположим, из запрошенных 18 байт на момент анализа ивента в файловом потоке ввода доступно всего 9 байт ... разумеется, ивент не просигналил еще ! ... а раз не просигналил, то и Result = 0...

ну и иная ситуация (та на которую ты намекаешь) - ивент просигналил, но в файловом потоке есть EOF ... тогда Read() вернет из overlapped-структуры то число байт, что находится в файловом потоке ДО Eof ... и вполне возможно, что до EOF ничего и не приходило ... тогда ситуация с Result = 0 так же объяснима


 
Digitman ©   (2004-03-19 11:18) [15]


> Verg ©   (19.03.04 10:55) [12]


нет, ну насчет того, что Read() сам по себе блокирующий, я согласен на все 100 ...

я имел ввиду саму операцию ввода/вывода, что задействуется внутри Read()

согласен - реализовали это метод крайне криво, посему лично я класс TWinSocketStream никогда не использую и другим категорически не рекомендую


 
Digitman ©   (2004-03-19 11:18) [15]


> Verg ©   (19.03.04 10:55) [12]


нет, ну насчет того, что Read() сам по себе блокирующий, я согласен на все 100 ...

я имел ввиду саму операцию ввода/вывода, что задействуется внутри Read()

согласен - реализовали это метод крайне криво, посему лично я класс TWinSocketStream никогда не использую и другим категорически не рекомендую


 
Verg ©   (2004-03-19 11:26) [16]


> предположим, из запрошенных 18 байт на момент анализа ивента
> в файловом потоке ввода доступно всего 9 байт ... разумеется,
> ивент не просигналил еще !


Ивент просигналит, именно просигналит, если в сокете есть хоть сколько-нибудь принятых байтов, хоть один!
Либо произошел разрыв петли, тогда getoverlappedresult вернет 0.


 
Verg ©   (2004-03-19 11:26) [16]


> предположим, из запрошенных 18 байт на момент анализа ивента
> в файловом потоке ввода доступно всего 9 байт ... разумеется,
> ивент не просигналил еще !


Ивент просигналит, именно просигналит, если в сокете есть хоть сколько-нибудь принятых байтов, хоть один!
Либо произошел разрыв петли, тогда getoverlappedresult вернет 0.


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


> [9] slgeo   (19.03.04 10:43)


Не знаю, прямо что и сказать - то один код показываешь, то другой.
Вот в последнем - почему ты так уверен, что признак конца (000000!) не попдет на границе принимаемых блоков?
Где гарантия, что ты его (эту последовательность) обнаружишь целиком в одном эелементарном буфере примема (256 байт)?


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


> [9] slgeo   (19.03.04 10:43)


Не знаю, прямо что и сказать - то один код показываешь, то другой.
Вот в последнем - почему ты так уверен, что признак конца (000000!) не попдет на границе принимаемых блоков?
Где гарантия, что ты его (эту последовательность) обнаружишь целиком в одном эелементарном буфере примема (256 байт)?


 
Verg ©   (2004-03-19 11:44) [18]

Этот код, при определенном размере передаваемого потока может не обнаружить признак конца твоего "файла" и будет продолжать ждать данные от собеседника. А тот, отправив все данные и признак конца 00000! просто закроет соединение.
Вот у тебя и nRead выскочит с нулем.


 
Verg ©   (2004-03-19 11:44) [18]

Этот код, при определенном размере передаваемого потока может не обнаружить признак конца твоего "файла" и будет продолжать ждать данные от собеседника. А тот, отправив все данные и признак конца 00000! просто закроет соединение.
Вот у тебя и nRead выскочит с нулем.


 
Digitman ©   (2004-03-19 12:03) [19]


> Verg ©   (19.03.04 11:26) [16]


проанализировал ..
согласен, просигналит .. я был не прав


 
Digitman ©   (2004-03-19 12:03) [19]


> Verg ©   (19.03.04 11:26) [16]


проанализировал ..
согласен, просигналит .. я был не прав


 
slgeo   (2004-03-19 12:43) [20]

>Verg
Ну а почему nRead всегда 0!!!


 
slgeo   (2004-03-19 12:43) [20]

>Verg
Ну а почему nRead всегда 0!!!


 
Digitman ©   (2004-03-19 12:54) [21]


> slgeo


приводи код кл.стороны
следы проблемы ведут туда


 
Digitman ©   (2004-03-19 12:54) [21]


> slgeo


приводи код кл.стороны
следы проблемы ведут туда


 
slgeo   (2004-03-19 12:58) [22]

FileSize := FileUtil.GetFileSize(strfile);
     //передаем команду на обновление с размером файла
     strFeedback := "UPDATE!"+ AddChar("0",IntToStr (FileSize),10)+"!";
     ClientSocket.SendText(strFeedback);
     ClientSocket.SendStream(TMyFileStream.Create (
       strFile, fmOpenRead or fmShareDenyWrite));
     ClientSocket.SendText("000000!");


 
slgeo   (2004-03-19 12:58) [22]

FileSize := FileUtil.GetFileSize(strfile);
     //передаем команду на обновление с размером файла
     strFeedback := "UPDATE!"+ AddChar("0",IntToStr (FileSize),10)+"!";
     ClientSocket.SendText(strFeedback);
     ClientSocket.SendStream(TMyFileStream.Create (
       strFile, fmOpenRead or fmShareDenyWrite));
     ClientSocket.SendText("000000!");


 
slgeo   (2004-03-19 13:01) [23]

function TMyFileStream.Read(var Buffer; Count: Integer): Longint;
begin
result:=inherited Read(Buffer, Count);
Form1.Gauge2.AddProgress(Count);
end;


 
slgeo   (2004-03-19 13:01) [23]

function TMyFileStream.Read(var Buffer; Count: Integer): Longint;
begin
result:=inherited Read(Buffer, Count);
Form1.Gauge2.AddProgress(Count);
end;


 
Digitman ©   (2004-03-19 13:05) [24]


> slgeo


почему ты, явно заострив внимание на блок.режиме принимающей стороны, ни словом не обмолвился о режиме передающей ?

это крайне важно !!


 
Digitman ©   (2004-03-19 13:05) [24]


> slgeo


почему ты, явно заострив внимание на блок.режиме принимающей стороны, ни словом не обмолвился о режиме передающей ?

это крайне важно !!


 
slgeo   (2004-03-19 13:11) [25]

я думаю это вполне само собой разумеющееся, обе стороны работают в блокирующем режиме


 
slgeo   (2004-03-19 13:11) [25]

я думаю это вполне само собой разумеющееся, обе стороны работают в блокирующем режиме


 
Digitman ©   (2004-03-19 13:20) [26]


> я думаю это вполне само собой разумеющееся


с чего бы "разумеющееся" ? режим одной стороны соединения не имеет никакого отношения к режиму другой стороны

вопрос здесь иной : а чем обосновано применение TWinSocketStream
на принимающей стороне и неприменение его же на передающей ? есть разумные доводы в пользу этой "солянки сборной" ?


 
Digitman ©   (2004-03-19 13:20) [26]


> я думаю это вполне само собой разумеющееся


с чего бы "разумеющееся" ? режим одной стороны соединения не имеет никакого отношения к режиму другой стороны

вопрос здесь иной : а чем обосновано применение TWinSocketStream
на принимающей стороне и неприменение его же на передающей ? есть разумные доводы в пользу этой "солянки сборной" ?


 
Verg ©   (2004-03-19 13:28) [27]


> [20] slgeo   (19.03.04 12:43)
> >Verg
> Ну а почему nRead всегда 0!!!


Когда "всегда"? Что значит "всегда"?
Не верю. Ты же вот не говоришь - как именно ты убедился, что ВСЕГДА 0.

Или ты чего-то не договариваешь или у тебя "поврежденная" Винда (что крайне маловероятно).

Ты же должен понимать, что "чудес" не бывает.


 
Verg ©   (2004-03-19 13:28) [27]


> [20] slgeo   (19.03.04 12:43)
> >Verg
> Ну а почему nRead всегда 0!!!


Когда "всегда"? Что значит "всегда"?
Не верю. Ты же вот не говоришь - как именно ты убедился, что ВСЕГДА 0.

Или ты чего-то не договариваешь или у тебя "поврежденная" Винда (что крайне маловероятно).

Ты же должен понимать, что "чудес" не бывает.


 
slgeo   (2004-03-19 13:35) [28]

так, начнем сначала:
и приемная и передающая сторона используют TWinSocketStream,
в нашем случае передающая сторона TServerClientThread, а именно сервер обрабатывающий запросы от нескольких клиентов. ПОэтому приведенный выше код [22] возможно ввел немного в заблудение. Этот код находится внутри метода ClientExecute экземпляра TServerClientThread.


 
slgeo   (2004-03-19 13:35) [28]

так, начнем сначала:
и приемная и передающая сторона используют TWinSocketStream,
в нашем случае передающая сторона TServerClientThread, а именно сервер обрабатывающий запросы от нескольких клиентов. ПОэтому приведенный выше код [22] возможно ввел немного в заблудение. Этот код находится внутри метода ClientExecute экземпляра TServerClientThread.


 
slgeo   (2004-03-19 13:41) [29]

> Verg
А убедился я поставив в итоге на эту конкретную машину Delphi и увидев под отладчиком значение переменной nRead = 0, причем данные (а именно команда "UPDATE!0013433220!") были прочитаны в буфер!


 
slgeo   (2004-03-19 13:41) [29]

> Verg
А убедился я поставив в итоге на эту конкретную машину Delphi и увидев под отладчиком значение переменной nRead = 0, причем данные (а именно команда "UPDATE!0013433220!") были прочитаны в буфер!


 
Digitman ©   (2004-03-19 13:42) [30]


> slgeo   (19.03.04 13:35) [28]


приводи ПОЛНЫЙ текст ClientExecute


 
Digitman ©   (2004-03-19 13:42) [30]


> slgeo   (19.03.04 13:35) [28]


приводи ПОЛНЫЙ текст ClientExecute


 
Digitman ©   (2004-03-19 13:48) [31]

с учетом деталей происходящего в [29] есть большое подозрение, что строчка

TMyFileStream.Create (strFile, fmOpenRead or fmShareDenyWrite)

вызвала исключение, в рез-те чего соединение на передающей стороне было закрыто тем или иным образом, что и явилось причиной Eof на принимающей стороне


 
Digitman ©   (2004-03-19 13:48) [31]

с учетом деталей происходящего в [29] есть большое подозрение, что строчка

TMyFileStream.Create (strFile, fmOpenRead or fmShareDenyWrite)

вызвала исключение, в рез-те чего соединение на передающей стороне было закрыто тем или иным образом, что и явилось причиной Eof на принимающей стороне


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

procedure TDbServerThread.ClientExecute;
var
 Stream: TWinSocketStream;
 FileSize : Integer;
 strfile : string;
begin
 Stream := TWinSocketStream.Create(ClientSocket, 30000);
 try
   while not Terminated and ClientSocket.Connected do
   strfile := CurDir+ "update.txt";
   if FileExists (strFile) then
   begin
     FileSize := FileUtil.GetFileSize(strfile);
     strFeedback := "UPDATE!"+ AddChar("0",IntToStr(FileSize),10)+"!";
     ClientSocket.SendText(strFeedback);
     ClientSocket.SendStream(TMyFileStream.Create (
       strFile, fmOpenRead or fmShareDenyWrite));
     ClientSocket.SendText("000000!");
   end;
 finally
   Stream.Free;
 end;
end;

function TMyFileStream.Read(var Buffer; Count: Integer): Longint;
begin
result:=inherited Read(Buffer, Count);
// Form1.Gauge2.AddProgress(Count);
end;


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

procedure TDbServerThread.ClientExecute;
var
 Stream: TWinSocketStream;
 FileSize : Integer;
 strfile : string;
begin
 Stream := TWinSocketStream.Create(ClientSocket, 30000);
 try
   while not Terminated and ClientSocket.Connected do
   strfile := CurDir+ "update.txt";
   if FileExists (strFile) then
   begin
     FileSize := FileUtil.GetFileSize(strfile);
     strFeedback := "UPDATE!"+ AddChar("0",IntToStr(FileSize),10)+"!";
     ClientSocket.SendText(strFeedback);
     ClientSocket.SendStream(TMyFileStream.Create (
       strFile, fmOpenRead or fmShareDenyWrite));
     ClientSocket.SendText("000000!");
   end;
 finally
   Stream.Free;
 end;
end;

function TMyFileStream.Read(var Buffer; Count: Integer): Longint;
begin
result:=inherited Read(Buffer, Count);
// Form1.Gauge2.AddProgress(Count);
end;


 
Digitman ©   (2004-03-19 13:55) [33]

мне вообще непонятно, на кой шут в дан.случае транслировать что бы то ни было в текстовом формате..

что такое "256" в [9] ? откуда взялось это число ?

твой ПИО предусматривает трансляцию префикса/постфикса ? его длина что, всегда равна 256 байт ?


 
Digitman ©   (2004-03-19 13:55) [33]

мне вообще непонятно, на кой шут в дан.случае транслировать что бы то ни было в текстовом формате..

что такое "256" в [9] ? откуда взялось это число ?

твой ПИО предусматривает трансляцию префикса/постфикса ? его длина что, всегда равна 256 байт ?


 
Verg ©   (2004-03-19 14:07) [34]


> [29] slgeo   (19.03.04 13:41)
> > Verg
> А убедился я поставив в итоге на эту конкретную машину Delphi
> и увидев под отладчиком значение переменной nRead = 0, причем
> данные (а именно команда "UPDATE!0013433220!") были прочитаны
> в буфер
!


Или были и до Read?


 
Verg ©   (2004-03-19 14:07) [34]


> [29] slgeo   (19.03.04 13:41)
> > Verg
> А убедился я поставив в итоге на эту конкретную машину Delphi
> и увидев под отладчиком значение переменной nRead = 0, причем
> данные (а именно команда "UPDATE!0013433220!") были прочитаны
> в буфер
!


Или были и до Read?


 
slgeo   (2004-03-19 14:13) [35]

> Verg
нет, это самый первый Read в обработчике


 
slgeo   (2004-03-19 14:13) [35]

> Verg
нет, это самый первый Read в обработчике


 
Verg ©   (2004-03-19 14:25) [36]


> [35] slgeo   (19.03.04 14:13)


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

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

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

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

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


 
Verg ©   (2004-03-19 14:25) [36]


> [35] slgeo   (19.03.04 14:13)


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

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

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

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

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


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

вот практически вся процедура принимающей стороны
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;


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

вот практически вся процедура принимающей стороны
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 15:28) [38]

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

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

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

   if FEvent.WaitFor(FTimeOut) <> wrSignaled then
     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;

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


 
Verg ©   (2004-03-19 15:28) [38]

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

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

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

   if FEvent.WaitFor(FTimeOut) <> wrSignaled then
     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 16:29) [39]

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


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

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


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


> slgeo


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

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

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


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


> slgeo


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

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

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



Страницы: 1 2 вся ветка

Форум: "Сети";
Текущий архив: 2004.04.11;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.72 MB
Время: 0.047 c
14-1082405495
Подорожник
2004-04-20 00:11
2004.05.09
Какие работы надо провести с машиной после зимы?


4-1079351543
Talla2k
2004-03-15 14:52
2004.05.09
аналог SelLength на WinApi


14-1082099069
nikitch
2004-04-16 11:04
2004.05.09
веб-камера


14-1081319370
int64
2004-04-07 10:29
2004.05.09
О провилах хорошего тона в программировании.


11-1068809937
aser
2003-11-14 14:38
2004.05.09
почему добавленный вручную в uses модуль после build пропадает ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский