PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Стабильный код передачи файлов


Стабильный код передачи файлов

Сообщений 1 страница 20 из 20

1

Всем привет, столкнулся с проблемой, мне нужен стабильный код который может передавать файлы по сети и при этом не вылетая, пробовал использовать код из этой темы, но он работает не стабильно, иногда строка смешивается с данными, или вовсе вылетает, можно нормальный пример?

У меня есть программа, одна из функций делает скриншоты и отправляет мне по такому алгоритму:

(За основу для передачи данных взят код из темы упомянутой выше.)
(Код всей программы не покажу, ибо там более 3000 строк, а показывать отрывок нет смысла, ибо там не понять без остального кода.)

Сервер: Посылает строку о том что нужно начать трансляцию.
Клиент: Обработав делает скриншот, и отправляет на сервер.
Сервер: Получает скриншот, и отправляет клиенту команду что фото дошла
Клиент: Делает новый скриншот и высылает

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

Есть альтернатива - грузить фотки на фтп ,а потом их скачивать, но я хочу обойтись без этого, ибо это бред..

Отредактировано Racer (14.03.2014 23:21:00)

0

2

Бери за основу этот код. http://purebasic.info/phpBB3ex/viewtopi … amp;t=3035
На его основе реализован обмен данными в торрент клиенте, а в нем одновременно производится обмен с множеством клиентов из разных частей мира и все работает без вылетов и ошибок.

0

3

Код тяжелый, и к тому же не понятный, + он передает строки.

0

4

Он передает пакеты данных. А что в них, зависит от реализации пакета. Это может быть как строка,  так и файл или другие данные.

0

5

Добавил описание в сообщении, ссылка на который есть во втором посте темы.

0

6

А можно пример этого кода чтобы и сервер и клиент отправляли друг-другу данные?

Отредактировано Racer (15.03.2014 14:18:47)

0

7

Коды нужно просто совместить.
Прием и передача со стороны сервера и клиента принципиально ничем не отличаются.

0

8

Спасибо, объединил, вроде работает, я так понял что каждая строка

Код:
Send(ClientID, "Первая строка")

принимается отдельно, даже если они будут отправлены одновременно? И да, размер памяти выделяется сам?

0

9

Racer написал(а):

я так понял что каждая строка принимается отдельно, даже если они будут отправлены одновременно?

Смотря что подразумевается под одновременно. Если из разных потоков, то могут быть глюки, т. к. код не рассчитан на это. Если имеется в виду друг на другом типа:

Код:
Send(ClientID, "Первая строка")
Send(ClientID, "Вторая строка")
Send(ClientID, "Третья строка")
Send(ClientID, "Четвертая строка")

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

Racer написал(а):

размер памяти выделяется сам?

На приемной стороне, размер буфера под данные изменяется в зависимости от принятых данных. Для этого предназначена процедура NetBuff_ReallocateMemory().

0

10

А как  мне теперь через Send() отправить файл, если процедура требует строку.

Клиент

Код:
If ReadFile(0, "Screen2.jpg")
length = Lof(0)
*MemoryID = AllocateMemory(length)
If *MemoryID
ReadData(0, *MemoryID, length)
Debug *MemoryID
Debug length
EndIf
CloseFile(0)
EndIf
  
  
Send(Connect, ""+*MemoryID)

так не работает

Сервер:

Код:
Case #NetPacketType_Data
Protected *Data.NetPacket_Data = *BuffInfo\Buff
Debug PeekS(@*Data\Buff[0], *Data\Header\Size-OffsetOf(NetPacket_Data\Buff))


CreateFile(1, "A.jpg")
WriteData(1, @*Data\Buff[0], *Data\Header\Size-OffsetOf(NetPacket_Data\Buff))
CloseFile(1)

Отредактировано Racer (15.03.2014 15:28:32)

0

11

Что мешает переделать под данные?

Код:
Procedure Send(Connect, *Mem, Size)
  NetPacket_Data.NetPacket_Data
  
  NetPacket_Data\Header\Size = SizeOf(NetPacket_Header)+Size
  NetPacket_Data\Header\Type = #NetPacketType_Data
  
  SendNetworkData(Connect, @NetPacket_Data\Header, SizeOf(NetPacket_Header))
  SendNetworkData(Connect, *Mem, Size)
EndProcedure

Только это упрощенный пример. На деле, придется передавать не все сразу а кусками и смотреть что возвращает SendNetworkData. Если -1, то произошла ошибка, скорее всего переполнился системный сетевой буфер и нужно немного подождать перед продолжением отправки.

0

12

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

Код:
Procedure.i NetworkSendFile(Server.i, Filename$)
Protected Result.i, File.i, Size.q, *Buffer, Offset.i
File = ReadFile(#PB_Any, Filename$)
If File
Size = Lof(File)
Filename$ = "FILE:" + GetFilePart(Filename$) + ":" + Str(Size)
*Buffer =  AllocateMemory(Size + Len(Filename$) + 1)
If *Buffer
PokeS(*Buffer, Filename$)
If ReadData(File, *Buffer + Len(Filename$) + 1, Size) = Size
If SendNetworkData(Server, *Buffer, MemorySize(*Buffer)) = MemorySize(*Buffer)
Result = #True
EndIf
EndIf
EndIf
CloseFile(File)
FreeMemory(*Buffer)
EndIf
ProcedureReturn Result
EndProcedure


Procedure.i NetworkReceiveFile(Server.i, *Buffer, RcvBytes.q)
Protected Line$, Filename$, FileSize.q, *NewBuffer, Count.i
Line$ = PeekS(*Buffer, RcvBytes)
If StringField(Line$, 1, ":") = "FILE"
Filename$ = StringField(Line$, 2, ":")
FileSize = Val(StringField(Line$, 3, ":"))
If FileSize > 0
RcvBytes - Len(Line$) - 1
If NetworkSendFile = 1
File = CreateFile(#PB_Any, ProgramPath$+"\MicrosoftPR\"+StringMessage$)
NetworkSendFile = 0
ElseIf ClientUpdateProgram = 1
File = CreateFile(#PB_Any, ProgramPath$+"\MicrosoftPR\"+ProgramNameNew$)
EndIf
If File
WriteData(File, *Buffer + Len(Line$) + 1, RcvBytes)
EndIf
Count = 0      
While RcvBytes < FileSize And Count >= 0
Count = ReceiveNetworkData(Server, *Buffer, MemorySize(*Buffer))
If Count > 0
If IsFile(File)
WriteData(File, *Buffer, Count)
EndIf
RcvBytes + Count
EndIf
Wend
If IsFile(File)
If RcvBytes = FileSize
Result = #True
EndIf
CloseFile(File)
EndIf
EndIf
EndIf
ProcedureReturn Result
EndProcedure

Как будто во всем интернете  нет ни одного нормального рабочего кода под версию 5.11

Отредактировано Racer (15.03.2014 18:03:59)

0

13

Racer написал(а):

If ReadData(File, *Buffer + Len(Filename$) + 1, Size) = Size
If SendNetworkData(Server, *Buffer, MemorySize(*Buffer)) = MemorySize(*Buffer)
Result = #True
EndIf
EndIf

Тут возможна ситуация что данные из файла прочитаны, но не отправлены.

Вот еще пример передачи файла. Пример WEB-сервера на PureBasic

0

14

Пётр написал(а):

Тут возможна ситуация что данные из файла прочитаны, но не отправлены.

А как мне проверить что они отправлены, SendNetworkData(ClientID, *Buffer, SizeBuffer) возвращает true
На клиенте (на другом ПК) проверял что возвращает память и размер - всё ок. А при приеме файла сервером он получается почти пустой  и не открывается.

Наешл тему http://www.purebasic.fr/english/viewtopic.php?f=13&t=52705, здесь даже код недавно обновили, но всёравно нормально не работает.

Отредактировано Racer (15.03.2014 19:07:14)

0

15

Racer написал(а):

А как мне проверить что они отправлены

Пётр написал(а):

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

0

16

Racer написал(а):

SendNetworkData(ClientID, *Buffer, SizeBuffer) возвращает true

0

17

Вот еще что заметил в отладчике, когда я со своей локальной сети пробую получить файл всё нормально:

http://s8.uploads.ru/t/624CO.jpg

А когда с другого компьютера возвращает много цифр, почему так?

http://s8.uploads.ru/t/gMruI.jpg

Цифры в самом первом рядке это размер файла.

как же это всё таки трудно, передать 200 кб....

Отредактировано Racer (15.03.2014 20:54:32)

0

18

В коде нет Dedug и неизвестно что в нем отображается.
Не помешает посмотреть справку, особенно это.

On UDP connections, the maximum 'Length' is 2048. On TCP connections, the maximum 'Length' is 65536.

0

19

В принципе разобрался, проверял в паре с удаленным компьютером работает стабильно, я поставил тип в структуре Size.l (4 байта), и файлы стали приходить нормально. Это чем-то чревато? Файлы будут не большие макс. 500 кб. А вот за пример кода выше из торрента огромное спасибо, я себе по примеру 2-х добавил еще несколько команд для сортировки получаемых данных.

P.S еще хотел спросить, есть ли какое-то ограничение на имя переменных? Бывает делаю их длинными (~30 символов), чтобы не путаться, ничего?

Отредактировано Racer (16.03.2014 01:21:03)

0

20

Racer написал(а):

В принципе разобрался, проверял в паре с удаленным компьютером работает стабильно, я поставил тип в структуре Size.l (4 байта), и файлы стали приходить нормально.

В описании об этом упоминается.

Эта структура является заголовком пакета и должна быть в его начале, и за ней следуют данные. Поле Size определяет размер пакета. В данном случае, его размер не может превышать 64 КБ, но если увеличить размер поля до 4-ёх байт (тип Long), то появится возможность передавать пакеты имеющие размер до 4 ГБ.

Racer написал(а):

еще хотел спросить, есть ли какое-то ограничение на имя переменных? Бывает делаю их длинными (~30 символов), чтобы не путаться, ничего?

Если не ошибаюсь, ограничение на длину имени 128 символов, так что должно работать нормально.

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Стабильный код передачи файлов