![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
||||
|
||||
|
В общем стоит задача написать чат (написан почти что, писал на основе КлиентСокет и Скрвер) и сделать возможным передачу файлов. Нашел несколько исходников передачи файлов через Сокеты... все не работают, получилось какие-то починить
. Но проблема встала следующая: при передаче файлов (метров например 700) форма вешается и сообщения до конца передачи файлов посылать нельзя будет ("будет" потому что я еще не встроил передачу файлов в чат). Нужно как-то замутить передачу в отдельном потоке, чтобы форма в это время не нагружалась. Поискал я что-то нечто подобное в разных разделах, найти ответ не удалось. Может кто-то сталкивался с подобной проблемой и имеется простенький исходник? |
|
#2
|
||||
|
||||
|
Если у тебя порции файлов передаются в цикле, то возможно хватит простого Application.ProcessMessages.
|
|
#3
|
||||
|
||||
|
Так, циклов нету, событие Ресив проихсдоит просто часто. Вот один исходник:
Код:
var l: Integer; buf: PChar; src: TFileStream; pat: string; begin pat:='hz.rar'; l:= Socket.ReceiveLength; GetMem(buf,l+1); Socket.ReceiveBuf(buf[0],l); if fileexists(pat) then src:= TFileStream.Create(pat, fmopenreadwrite) else src:= TFileStream.Create(pat, fmCreate); src.Seek(0,soFromEnd); src.WriteBuffer(buf[0],l); src.Free; FreeMem(buf); end; Есть второй вариант, там идет работа с TMemoryStream - работает лучше, тормозит только на сохранение файла, но данный вариант меня не устраивает. Последний раз редактировалось Agito, 22.06.2009 в 21:57. |
|
#4
|
|||
|
|||
|
Вероятность нахождения такого исходника невелика. Поэтому попробую подтолкнуть к одному из вариантов:
Нужно писать отдельный поток (это Вы уже определили) на передачу файла. Причем - гораздо выгоднее писать один поток для 2х действий (что бы не зависал клиент не только получателя но и отправителя) - передача и прием файлов, которые вызываться будут в зависимости от поступившей на основной сокет команды. Этот поток должен содержать свой сокет (или основной сокет переводить на режим совместимости с потоками. Давно не баловался - нюансов не помню). В итоге должна быть примерно следующая схема: 1.При попытке отправить файл - стартует поток с задачей "отправить файл", порт сокета рекомендуется использовать отличный от "коммуникационного". Клиент-отправитель направляет по коммуникационному порту запро на принятие файла 2.Клиент-получатель при получении запроса на принятие файла стартует поток с задачей "получить файл" (в качестве параметров можно использовать ip адрес клиента-отправителя и порт). Далее уже поток направляет запрос о том, что "готов принять файл" и готовит сокет для принятия файла 3.Клиент-отправитель при получении запроса о принятии файла - "стартует" передачу. В дополнение можно прикрутить кучу дополнительных плюшек в виде формы с отображением процесса передачи, проверка CRC по завершению передачи для фиксирования целостности файла, при нарушении CRC - повторная попытка передать файл и многое другое, чего душе угодно. В общем, поскольку с сетями по всей видимости разобрались - достаточно почитать немного литературы об организации потоков. Так же хочу предупредить - локализация ошибок в потоках бывает довольно сложным занятием, будьте внимательны к мелочам. |
|
#5
|
||||
|
||||
|
Эх, в том-то и дело, что я знаю, что нужно делать, но вот как... то есть у меня одна проблема - реализация, почитав про потоки понял лишь как простой кусок кода замутить в отдельном потоке, но событие так и не удалось выгрузить.
|
|
#6
|
|||
|
|||
|
Цитата:
Если речь идет о передаче параметров потоку то тут возможен вариант создания своего конструктора потока (с нужными параметрами) или создание приостановленного потока, далее заполнение различных, необходимых для работы параметров и по завершению запуск потока. |
|
#7
|
||||
|
||||
|
Цитата:
. Смысл в том, что сначала создается поток, а уже потом в него засовывается событие "Ресив". С параметрами могут возникнуть проблемы, так как возможна разсинхронизация между "Ресив" и нашим потоком, то есть надо не через параметры... а конкретно прям все события засунуть в отдельный поток. |
|
#8
|
|||
|
|||
|
Цитата:
По поводу "вгрузить", как я и описал выше - можно создать свой конструктор (тот, который Create) с нужными параметрами и создавать поток с помощью этого конструктора, а можно создавать приостановленный поток стандартным конструктором, передавать ему параметры и запускать выполнение потока. Не очень понятно какой именно рассинхронизации Вы опасаетесь, опишите подробнее пожалуйста. |
|
#9
|
||||
|
||||
|
В общем замутил с TMemoryStream, из-за того, что время поджимало очень сильно, всем спасибо, хоть мы ни к чему и не пришли
. |