Форум: "Сети";
Текущий архив: 2003.03.27;
Скачать: [xml.tar.bz2];
ВнизПодвисание приложения во время передачи файла... Найти похожие ветки
← →
SeNtiMeL (2003-02-03 03:06) [0]Когда начинаешь передавать файл через Socket.SendStream то подвисает окно программы на время передачи. Как этого избежать.
То же самое происходит и при получениии файла клиентом.
В программах типа IRC отправка файла происходит просто здорово без зависаний и т.п....
Как сделать без зависаний ?
← →
ole (2003-02-03 05:39) [1]Отправляй в отдельном Thread"е
← →
Digitman (2003-02-03 11:26) [2]либо используй неблок.режим гнезда в осн.код.потоке
см. событие OnWrite()
← →
SeNtiMeL (2003-02-03 17:38) [3]а если не сложно приведите пример...
← →
ole (2003-02-04 04:55) [4]Создай Thread: (очень просто)
В методе Execute организуй отправку.
Передать данные потоку, я думаю, не проблема
> см. событие OnWrite()
Если по совету Дижитмэна, то, скорей всего, SendStream не прокатит. Там придется посылать поблочно, ожидая события OnWrite, которое скажет тебе, что очередь передачи свободна и ты можешь кинуть новую порцию данных.
← →
Digitman (2003-02-04 08:17) [5]
> ole
> скорей всего, SendStream не прокатит
Прокатит. Ничто не мешает в событии OnWrite() дописать, если нужно, в "хвост" еще не полностью переданного потока и тут же вновь вызвать этот же SendStream()
← →
ole (2003-02-04 12:20) [6]
> и тут же вновь вызвать этот же SendStream()
Тогда непонятен смысл твоего предложения. У него все виснет и так, а ты предлагаешь что б вообще все повисло.
Как я понимаю, пока не отправится весь блок данных через SendStream, буфер передачи будет постоянно занят (полон).
Другое дело, если отправлять буфера, то всегда можно увидеть через OnWrite, что следует отправить еще один и тд и тп.
И еще, SendStream освободит хэндл, данный ему для передачи данных, что же ты предлагаешь ему отправлять???
← →
Digitman (2003-02-04 13:43) [7]
> ole
> У него все виснет и так, а ты предлагаешь что б вообще все
> повисло.
Не говори ерунды. Ничего не повиснет. Заполнение 8к-буфера происходит мгновенно. После этого send-метод в любом случае вернет управление, даже если требуется к передаче в сотни и тысячи раз больше данных.
> Как я понимаю, пока не отправится весь блок данных через
> SendStream, буфер передачи будет постоянно занят (полон).
> Другое дело, если
Неверно понимаешь. Смотри реализацию SendStreamPiece, прежде чем рассуждать и делать выводы.
> Другое дело, если отправлять буфера, то всегда можно увидеть
> через OnWrite, что следует отправить еще один и тд и тп.
Чем тебе TMemoryStream не буфер ? Передал его в метод SendStream(), получил назад управление, проанализировал результат.
Читаем хэлп :
The value returned by SendStream indicates whether any information was successfully written to the connection.
Что, трудно так понять ? True - весь поток передан. False - частично. Если частично, то это означает, что stream-объект еще не разрушен и можно обратиться к любым его св-вам (например, Write для записи в поток доп.данных), в т.ч. св-ву Position (покажет, сколько реально данных на этот момент "вытолкнуто" через буфер передачи в канал)
И, если частично, то не следует "пыжиться", пытаясь следом же вызвать снова SendStream для передачи оставшегося фрагмента потока. Следует дождаться OnWrite и тогда уж вызывать SendStream для ТОГО ЖЕ объекта stream С ТЕМ ЖЕ его св-вом Position, чтобы SendStreamPiece продолжил чтение очер.порции потока в буфер передачи С ТОГО ЖЕ места, с которого предыдущая попытка оказалась неуспешной.
← →
Digitman (2003-02-04 13:50) [8]Вот фрагменты кода, работающего с использованием SendStream в неблок.режиме
TOutgoingMemStream = class(TMemoryStream)
private
FOnDestroy: TNotifyEvent;
public
constructor Create(OnDestroy: TNotifyEvent);
destructor Destroy; override;
end;
...
constructor TOutgoingMemStream.Create(OnDestroy: TNotifyEvent);
begin
inherited Create;
FOnDestroy := OnDestroy;
end;
destructor TOutgoingMemStream.Destroy;
begin
if Assigned(FOnDestroy) then
FOnDestroy(Self);
inherited Destroy;
end;
...
procedure TSocketTransport.DoOnOutgoingStreamDestroyed(Sender: TObject);
begin
FOutgoingStream := nil;
end;
// DataBlock sender
function TSocketTransport.Send(const Data: IDataBlock): Integer;
var
StreamToSend: TMemoryStream;
StreamSize: DWord;
CurPos: DWord;
WaitEvent: THandle;
begin
Result := 0;
if Assigned(Data) then
begin
if ((Data.Signature and CallSig) = CallSig) and (Data.Context = 0) then
begin
WaitEvent := CreateEvent(nil, False, False, nil);
Win32Check(WaitEvent <> 0);
Data.Context := WaitEvent;
end;
Result := Data.Context;
InterceptOutgoing(Data);
StreamToSend := TMemoryStream(Data.Stream);
StreamSize := StreamToSend.Size;
LockOutStream;
try
if not Assigned(FOutgoingStream) then
FOutgoingStream := TOutgoingMemStream.Create(DoOnOutgoingStreamDestroyed);
try
CurPos := FOutgoingStream.Position;
FOutgoingStream.Position := FOutgoingStream.Size;
FOutgoingStream.WriteBuffer(StreamToSend.Memory, StreamToSend.Size);
FOutgoingStream.Position := CurPos;
FWinSocket.SendStream(FOutgoingStream);
except
FOutgoingStream.Free;
raise;
end;
finally
UnLockOutStream;
end;
end;
end;
// OnWrite handler
procedure TSocketTransport.WriteEventHandler(Sender: TObject; Socket: TCustomWinSocket);
begin
try
Socket.SendStream(FOutgoingStream);
except
FOutgoingStream.Free;
raise;
end;
end;
← →
SeNtiMeL (2003-02-05 02:43) [9]Спасибо тебе большое :)
← →
ole (2003-02-06 14:00) [10]ДиджитМэн:
Спасибо. Действительно все просто.
Вот, если б все твои коментарии были такими подробными... :)
← →
Digitman (2003-02-06 16:44) [11]
> ole
Конечно, просто)
Вот если бы все программеры взяли бы за полезную привычку, когда что-то непонятно, заглядывать в документацию и исх.тексты)...
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2003.03.27;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.007 c