| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Сети > передача файла пакетами через clientsocket |
| Автор: den2005r 5.2.2010, 13:38 |
| всем привет. долбаюсь не первый день но так и не пойму почему не передаются или плохо передаются exe файлы размером по 70мб. и то допишет то не допишет подскажите получается не фига....... обращение к отправке Код: if ClientSocket1.Active then begin FStream:=TFileStream.Create(Edit2.Text,fmOpenRead); Send777(FStream, clientsocket1, Label18, ProgressBar1); FStream.Free; end; отправка Код: procedure tform1.Send777(FStream: TFileStream; Clientsocket: Tclientsocket; StatusLabel :Tlabel; ProgressBar :TProgressBar); var i,j,count: integer; buf : array[1..9000] of Char; begin i:=round(FStream.Size/9000); if (i*9000<FStream.Size) then i:=i+1; ProgressBar.Max:=i; clientsocket.socket.Sendtext('count'+IntToStr(i)+'#'+ExtractFileName(edit2.text)+'#'+inttostr(fstream.size)+'#'); Application.ProcessMessages; for j:=1 to i do begin if i=j then count:=FStream.Read(buf,FStream.Size-((i-1)*9000)) else count:=FStream.Read(buf,length(buf)); clientsocket.socket.SendBuf(buf,count); StatusLabel.Caption:='передача '+IntToStr(j)+' из '+IntToStr(i) ; ProgressBar.Position:=j; while get_accept=false do begin sleep(1); Application.ProcessMessages; end; get_accept:=false; end; Clientsocket.Socket.SendText('free'); end; прием Код: if first_=false then begin if copy(text,1,5)='count' then begin delete(text,1,5); get_buffers:=StrToInt(copy(text,0,pos('#',text)-1)); first_:=true; Label6.Caption:=inttostr(get_buffers); delete(text,1,pos('#',text)); wa:=copy(text,0,pos('#',text)-1); delete(text,1,pos('#',text)); razmer_file:=strtoint(copy(text,0,pos('#',text)-1)); Label19.caption:=inttostr(razmer_file); rrr := TfileStream.Create('C:\'+wa,fmCreate); get_buf_num:=0; text:=''; ProgressBar1.Max:=razmer_file; end; end else begin if pos('free',text)>0 then begin delete(text,1,4); first_:=false; end; adata:=TStringStream.Create(text); rrr.Position:=rrr.Size; rrr.CopyFrom(AData,AData.Size); Label20.caption:=inttostr(rrr.size); adata.free; get_buf_num:=get_buf_num+1; ProgressBar1.Position:=rrr.Size; Label7.Caption:=inttostr(get_buf_num); Serversocket1.socket.connections[0].Sendtext('*gotovo*'); if first_=false then rrr.free; end; |
| Автор: kami 5.2.2010, 18:51 |
| Из кода ничего не понял, если честно. Что за переменная GetAccept, откуда она берется и где выставляется в True Непонятно, откуда при приеме берется text, почему он обнуляется периодически, хотя при приеме и передаче опустошать буфер вручную категорически нельзя. Пройдитесь по нему трассировкой. В дополнение - Вы учитываете в коде такие особенности работы TCP как разбиение и склейка пакетов? Как пример: отправляем '123' и за ним '456'. На прием может прийти: '12' и потом '3456' или '1234' и '56' или '123456'. Порядок следования байт будет тот же, а вот за сколько событий OnRead - это никому не известно. (это к слову про text=''). |
| Автор: den2005r 5.2.2010, 19:08 | ||
выставляется при принятии ответа о принятии пакета. я просто создаю строковый поток из которого копирую в файловый поток. освобождаю строковый поток. если файл готов освобождаю файловый поток.
|
| Автор: den2005r 6.2.2010, 01:38 | ||
| count это команда на принятие файла далее идет имя файла но то ерунда. прийти 'count32791' а потом '44# не может идет всё вместе как не проверял. о создаю строковый поток из которого копирую в файловый поток. Зачем такие телодвижения? Почему сразу не записать в TFileStream? затем что не могу понять как писать сразу в поток.
потому что отошлет этот текст тока по окончании цикла поэтому и уверен. в этом примере может где то и есть недочеты я не спорю. про склейку и расклейку пакетов ваще ничего незнаю... хочу его просто довести до ума. этот пимер передачи выдрал из передачи файла на протоколе udp и переделал под себя. всё получается тока некоторые exe файлы криво доходят остальные доходят как надо. я таким методом фильм передал и размер был байт в байт и совершенно не поврежден.... ах да есть ещё нагрузка на проц но я её убрал небольшой задержкой возможно это неправильный метод... как довести его до ума подскажите пожалуйста. заранее благодарен. если что стучите в асю 453174586 |
| Автор: kami 6.2.2010, 01:55 | ||||||||||
Без комментариев.
Последний раз говорю: если передали какой-то буфер, а за ним текст, то это не значит, что придет сперва буфер, а потом (отдельно) текст. Они вполне могут СКЛЕИТЬСЯ. и при приеме получится остаток_буфера_файла_'free'. И я на основные указал - это неучитывание разбиения/склейки пакетов и (главное) отсутствие анализа результата SendBuf. Пока не осмыслите вышесказанные сообщения дальнейший диалог считаю бессмысленным. Посмотрите другие темы с участием TClient|TServerSocket в этом форуме.
Добавлено через 2 минуты и 54 секунды
UDP и TCP это два совершенно разных протокола, и работать с ними нужно по разному. UDP не гарантирует доставку буфера, но если буфер доставлен, то за ОДНО событие приема. TCP гарантирует доставку буфера, но за сколько событий приема - никому не известно. Добавлено через 4 минуты и 6 секунд
Вам крупно повезло. |
| Автор: den2005r 6.2.2010, 03:08 | ||||||
причем не один раз. да все файлы с любым расшиоением норм передаёт аот тока на некоторых exe файлах обрывается почему то.
это while clientsocket.socket.SendBuf(buf,count)<>count do sleep(10); или я не прав?
обьясни пожалуйста... оч хочется узнать как и что... долбусь не один день... или как лучше передавать фала на сокетах тока чтоб можно было выводить прогресс отдачи и приёма в сети не смог найти |
| Автор: kami 6.2.2010, 03:31 | ||||||||
Нет. Это (если Buf:string, переменная экземпляра класса)
Общий принцип работы приемной части: имеем буфер (в private секции класса).
|
| Автор: den2005r 6.2.2010, 14:24 | ||
| спасибо за обьяснение кое что понял. хотя не толком но разберусь. слушай а вот переменные CanWrite и Writed я так понял string или я ошибаюсь? и
|
| Автор: kami 6.2.2010, 14:32 |
Неправильно понял. Смотри хелп по функциям min и TStream.Write, а именно - какой тип они возвращают. Добавлено через 5 минут и 54 секунды А я откуда знаю, какой выбран признак конца приема заголовка? Вроде, заголовок у Вас состоит из: признак_начала+имя_файла+размер_файла+признак_конца. Вот по признаку_конца заголовка и нужно ориентироваться. |
| Автор: den2005r 6.2.2010, 15:02 |
| так поток файловый будет или TStream простой? и по скока лучше разбмвать файл... я думаю может разбивать его так чтоб пакет весил 10кб как ты думаешь? |
| Автор: kami 6.2.2010, 15:06 |
Все виды потоков - наследники абстрактного TStream. RTFM. Примеров в сети именно по TCP протоколу хватает. Удачи. |
| Автор: kami 6.2.2010, 15:27 |
| В завершение - код, который я использую для простых задач по сетевому обмену. Код неплохо комментирован. Правда, без доработки он не будет отображать, сколько данных реально передано/принято. |
| Автор: den2005r 6.2.2010, 17:35 |
| спасибо огромное. ато в сети чето не могу найти не чего толкового |
| Автор: den2005r 6.2.2010, 21:07 | ||||||||
а если это buf : array[1..10000] of Char; тогда как? и если это отдельная процедура такая вот
обращение к ней
|
| Автор: kami 6.2.2010, 21:29 |
| Плохо. Все объяснения, примеры кода, общие принципы работы с TClient|TServerSocket - впустую. Перечитайте, уловите идею, и не выдирайте куски из моего кода, пытаясь совместить со своим. Вам нужно полностью.ПОЛ-НОСТЬ-Ю. пересмотреть подход к передаче/приему данных с помощью этих компонентов. Добавлено через 1 минуту и 55 секунд Или переходите на indy. Там, вроде, все проще с этим. Но с Indy я не знаком абсолютно. Добавлено через 3 минуты и 39 секунд При использовании передачи данных по сети Application.ProcessMessages не нужно абсолютно. Это кривой костыль, позволяющий хоть как-то скрыть недостатки работы. |
| Автор: den2005r 6.2.2010, 21:40 |
| он сложноват для меня. попроще че нить есть? но а как тогда ждать ответа от сервака о том что он принял пакет? не тока не Indy я сним ваще некак |
| Автор: kami 6.2.2010, 21:49 | ||||
Если хочется отправить кусок в 10 кб это НЕ ЗНАЧИТ, что отправятся все 10кб. Больше повторять не буду.
Удалить и сделать другой.
Пакет будет принят в любом случае, если он отправлен в сеть. Это особенность TCP. Если он будет не принят, то соединение будет уничтожено. Поэтому не нужно ничего ждать. |
| Автор: den2005r 6.2.2010, 21:55 | ||
ну а начать то с чего?хотелось бы с чего стартануть... тот что ты мне пример дал там надо неделю разбираться. ах вот хотел спросить на TCP есть возможность отправки и с сервера и с криента как на clientsocket и serversocket ? |
| Автор: kami 6.2.2010, 22:17 | ||||||
Например, с моих объяснений в этой теме и
Начните с азов. Ибо TCP - это протокол обмена данными по сети. А TClient и TServerSocket - это компоненты, являющие собой минимальную надстройку над виндовыми функциями работы с TCP.
Dixi. |
| Автор: Mikel 9.2.2010, 12:55 |
| Лучше сделать свой протокол над tcp/ip - классика это все что летит объединяешь в пакеты, а пакеты состоят из <размер><данные><CRC> как принял целый не битый пакет, отправляешь на обработку. |