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

Вниз

С мольбой о помощи взываю!!!   Найти похожие ветки 

 
Polevi   (2001-10-17 11:45) [0]

Файл пытаюсь переслать :-)))
Все статьи прочитал, в форумах смотрел - у людей все работает, у у меня нет :((

Отсылаю

procedure TForm1.csConnect(Sender: TObject; Socket: TCustomWinSocket);
var
FS:TFileStream;
begin
FS:=TFileStream.Create("sour.ext",fmOpenRead);
cs.Socket.SendStream(FS);
FS.Free;
end;

Принимаю

procedure TClientThread.ClientExecute;
var
FS:TFileStream;
WSS:TWinSocketStream;
RL:integer;
begin
FS:=TFileStream.Create("dest.ext",fmCreate or fmOpenWrite);
WSS:=TWinSocketStream.Create(ClientSocket,20000);

try
while (not Terminated) and ClientSocket.Connected do
if WSS.WaitForData(20000) then
begin
RL:=ClientSocket.ReceiveLength;
if FS.CopyFrom(WSS, RL)=0 then break;
end;
finally
begin
ClientSocket.Close;
WSS.Free;
FS.Free;
end;
end;
end;

На маленьких файлах все работает..
Но если размер больше 4096 -
На строке CopyFrom - Stream read error

Я понимаю что тема заезжена - но не вижу я ошибки в коде!!
Помогите, плиз..


 
Digitman   (2001-10-17 12:52) [1]

procedure TClientThread.ClientExecute;
var
FS:TFileStream;
RL:integer;
SocketEvent: THandle;
buf: Pointer;
Msg: TMsg;
begin
try
FS:=TFileStream.Create("dest.ext",fmCreate or fmOpenWrite);
SocketEvent := WSACreateEvent;
WSAEventSelect(ClientSocket.SocketHandle, SocketEvent, FD_READ or FD_CLOSE);
try
while (not Terminated) and ClientSocket.Connected do

case MsgWaitForMultipleObjects(1, SocketEvent, False, INFINITE, QS_POSTMESSAGE) of
WAIT_OBJECT_0:
begin
RL:=ClientSocket.ReceiveLength;
if RL > 0 then begin
GetMem(buf, RL);
try
RL := ClientSocket.ReceiveBuf(buf^, RL);
FS.Write(buf^, RL)
finally
FreeMem(buf);
end;
end
end;
WAIT_OBJECT_0 + 1:
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
DispatchMessage(Msg);
end;
WAIT_ABANDONED: break;
end;
finally
CloseHandle(SocketEvent);
ClientSocket.Close;
FS.Free;
end;
except
// обработка ошибок
end;
end;


 
Evegeniy_S   (2001-10-17 12:53) [2]

а clienttype у тебя на сокете blocking?


 
Polevi   (2001-10-17 13:16) [3]

2Evegeniy_S
blocking

2Digitman
SocketEvent := WSACreateEvent; - здесь AV выскакивает :(
И если не трудно - можно небольшие комментарии?
Я не вижу здесь тайм-аута, например..


 
Digitman   (2001-10-17 13:51) [4]

что-то я глубоко сомневаюсь, что именно на SocketEvent := WSACreateEvent AV возбудится ...

Да, вот еще, в конце - не CloseHandle(SocketEvent), а WSACloseEvent(SocketEvent)

насчет тайм-аута - вместо INFINITE поставь время в мс и добавь в блок case..of вариант WAIT_TAIMAUT, в котором принимай решение, ждать дальше или закругляться


 
Polevi   (2001-10-17 14:25) [5]

Хм..
WSACreateEvent лежит в sconnect..

Вот эту ф-ию надо вызвать видимо???

function LoadWinSock2: Boolean;
const
DLLName = "ws2_32.dll";
begin
Result := hWinSock2 > HINSTANCE_ERROR;
if Result then Exit;
hWinSock2 := LoadLibrary(PChar(DLLName));
Result := hWinSock2 > HINSTANCE_ERROR;
if Result then
begin
WSACreateEvent := GetProcAddress(hWinSock2, "WSACreateEvent");
WSAResetEvent := GetProcAddress(hWinSock2, "WSAResetEvent");
WSACloseEvent := GetProcAddress(hWinSock2, "WSACloseEvent");
WSAEventSelect := GetProcAddress(hWinSock2, "WSAEventSelect");
end;
end;

Вызываю - AV пропадает, ессно..
Но возникает какаято жуткая тормозня и в итоге неичего не копируется..

?


 
Digitman   (2001-10-17 14:40) [6]

какая еще тормозня ? ты код трассировать умеешь ? оттассируй пошагово ClientExecute() - только тогда будешь иметь представление, что делается в каждой строчке. И вопрос сам по себе отпадет.


 
Polevi   (2001-10-17 15:23) [7]

Оттрассировал..
Почему "тормозит" понял

if RL > 0 then begin
GetMem(buf, RL);
try
RL := ClientSocket.ReceiveBuf(buf^, RL);
FS.Write(buf^, RL)
finally
FreeMem(buf);
end;

Так вот если RL<=0 то цикл зависает, и ни по какому тайм-ауту не выходит..
Если поставить else break; - то первые 4k копируются и все... (else break срабатывает, видимо)
"Видимо" потому что в пошаговом режиме все вроде копируется, а если точки останова убрать - начинается см. выще.

Щас полезу в исходники разбираться..
Халява не прошла :-)))




 
Polevi   (2001-10-17 16:13) [8]

Мдаа..
Переделал первоначальный вариант - отказался от CopyFrom, сделал все ручками - и все заработало на славу :-))
Вот ведь как бывает..


 
Digitman   (2001-10-17 16:37) [9]

Ты пойми, что сервер ничего не знает о полном размере данных, который клиент хочет передать. Для этого клиент перед посылкой собственно данных должен послать некий префикс, значение которого позволит серверу определиться, какой длины данные суммарно будут переданы. И в цикл нужно добавить условие (переменная-счетчик, работающий на вычитание размера очер.порции принятых данных, начальное значение которой формируется из считанного префикса), проверяющее, все ли данные считаны. Протокол-то - поточный ! Цикл надо прервать, когда Счетчик = 0, тогда и файл закроется и обработка завершится.
Приведенный код - лишь скелет, показывающий, как работать с поточным гнездом. Доработай его сам (и - осознанно, а не методом тыка !) с учетом этих замечаний - и убедишься в преимуществе над использованием TWinSocketStream


 
Polevi   (2001-10-17 18:39) [10]

Да, я все осознал, спасибо :-)
Я просто почемуто думал, что если ReceiveLength=0 то значит все уже скопировано..
Но все равно непонятно, почему по таймауту не выходил я из цикла..
Вместо INFINITE ставил занчение в милисек и на TIMEOUT не выходил..
Ну впрочем это видимо руки у меня кривые :-)


 
Digitman   (2001-10-18 08:52) [11]

>Polevi
Я еще вот чего важное забыл (спешил, извини уж, но - мог бы и сам догадаться, почитав хэлп на сабж)

Всякий раз в блоке WAIT_OBJECT_0 перевым делом нужно сбросить сигнал объекта синхронизации SocketEvent в нач.сотояние вызовом WSAResetEvent(SocketEvent), иначе он останется в сигналящем состоянии и ты больше не дождешься его срабатывания по событиям в гнезде.

Можно обойтись и без WSAResetEvent(), но тогда нужно использовать вызов WSAEnumNetworkEvents(), автоматически сбрасывающий сигн.объект. Это чуть сложнее, но зато дает большую гибкость в обработке гнездовых событий (в т.ч. немедленное получение инфы об ошибках, связанных с тем или иным событием без необходимости их обнаружения иными методами/вызовами)


 
Polevi   (2001-10-18 10:07) [12]

Спасибо, буду разбираться.



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

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

Наверх





Память: 0.47 MB
Время: 0.005 c
7-42585
fsp
2001-09-29 21:15
2002.01.14
sender:Tobject


3-42349
Dush
2001-12-11 11:11
2002.01.14
Delphi+InterBase=Книга


3-42352
МаксБ
2001-12-11 15:05
2002.01.14
Форматирование даты


14-42553
paul_shmakov
2001-11-19 15:10
2002.01.14
Рихтер


1-42418
Wetnose
2001-12-27 07:09
2002.01.14
KeyDown для ScrollBar a





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский