Передача бинарных файлов через винсок

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
CapsLock
Начинающий
Начинающий
 
Сообщения: 10
Зарегистрирован: 16.11.2008 (Вс) 23:42

Передача бинарных файлов через винсок

Сообщение CapsLock » 19.11.2008 (Ср) 20:30

Есть код для передачи файлов. Знаю, что тупо и медленно по байту, но не работает же как надо!

Код: Выделить всё
Open a For Binary As 1 Len = 1
Dim Byt As Byte
For i = 1 To FileLen(a)
  Get 1, i, Byt
  DoEvents
  WS.SendData Byt
Next i
Close 1


a - это путь к файлу
С другой стороны разумеется

Код: Выделить всё
Private Sub WS_DataArrival(ByVal bytesTotal As Long)
Dim data As Byte
WS.GetData data
Put 1, i, data
i = i + 1
End Sub


текстовые файлы передаются идеально, 100% соответствие, бинарные же, в часности exe, после передачи имеют тотже размер и ту же иконку, но при запуске "Файл ХХХ не является приложением Win32"

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

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Re: Передача бинарных файлов через винсок

Сообщение tyomitch » 19.11.2008 (Ср) 22:04

Код записи выглядит поломанным: байты в файле нумеруются с 1 (не с 0)
Изображение

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Передача бинарных файлов через винсок

Сообщение awl100Alex » 19.11.2008 (Ср) 23:02

tyomitch
Верно подметил! Видимо это только кусок кода... Put мгновенно выдает ошибку, если номер записи в файл начинается с нуля!

CapsLock
А зачем передавать по байту??? Если файл будет слишком большим, то дождаться окончания передачи, можно будет лишь в новом столетии. :)
Попробуй сразу весь EXE передать...

Код: Выделить всё
Dim Byt() As Byte 'Создаем динамический массив...

Private Sub Command2_Click()

'Откроем файл...
Open a For Binary As #1
ReDim Byt(LOF(1))
Get #1, , Byt 'Загружаем байты в массив
WS.SendData Byt()
Close #1

End Sub

На приеме...
WS.GetData data
Put #1, 1, data() ‘запись с единицы!!! Или просто - Put #1, , data()
Последний раз редактировалось awl100Alex 19.11.2008 (Ср) 23:08, всего редактировалось 1 раз.

CapsLock
Начинающий
Начинающий
 
Сообщения: 10
Зарегистрирован: 16.11.2008 (Вс) 23:42

Re: Передача бинарных файлов через винсок

Сообщение CapsLock » 19.11.2008 (Ср) 23:05

Походу в файле нет нулевого байта. По крайней мере

Код: Выделить всё
Get 1, 0, Byt


выдаёт ошибку

CapsLock
Начинающий
Начинающий
 
Сообщения: 10
Зарегистрирован: 16.11.2008 (Вс) 23:42

Re: Передача бинарных файлов через винсок

Сообщение CapsLock » 19.11.2008 (Ср) 23:08

awl100Alex
Ой точно!!! совсем забыл))) там процедурой раньше i = 1 в файле, который отвечает за запись)))))

А по поводу медленной скорости, так весь файл передавать низя - максимум 8байт кажется за раз. Или модет килобайт)) помню что восемь. Налажу такую передачу - буду делить и слать кусками

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Передача бинарных файлов через винсок

Сообщение awl100Alex » 19.11.2008 (Ср) 23:11

"...весь файл передавать низя..." - а ты пробовал???

CapsLock
Начинающий
Начинающий
 
Сообщения: 10
Зарегистрирован: 16.11.2008 (Вс) 23:42

Re: Передача бинарных файлов через винсок

Сообщение CapsLock » 19.11.2008 (Ср) 23:14

awl100Alex

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

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Передача бинарных файлов через винсок

Сообщение awl100Alex » 19.11.2008 (Ср) 23:20

CapsLock
Ну, тогда действительно нужно передавать кусками. Может так?..

Код: Выделить всё
Dim Byt() As Byte 'Создаем динамический массив...

Private Sub Command2_Click()

'Откроем файл...
Open a For Binary As #1
Do
Byt = String(1024, " ") 'Заполняем массив в 1 КБайт пустыми символами
Get #1, , Byt()
WS.SendData Byt()
Loop Until EOF(1)
Close #1

End Sub

CapsLock
Начинающий
Начинающий
 
Сообщения: 10
Зарегистрирован: 16.11.2008 (Вс) 23:42

Re: Передача бинарных файлов через винсок

Сообщение CapsLock » 19.11.2008 (Ср) 23:33

Эх непашет:(
Код: Выделить всё
Get #1, , Byt()

вот тут Out of memory пишет
Массив то неопределённой длины, несмотря на то, что в нём там записано чтото. А если его объявить
Код: Выделить всё
Dim Byt(1 To 1024) As Byte

То опять ошибка. Походу просто при помощи одного вызова get весь массив не заполнить, нужно циклом.

Кстати, вопрос из начала темы всё ещё актуален

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Передача бинарных файлов через винсок

Сообщение awl100Alex » 19.11.2008 (Ср) 23:43

Так я же тебе черновик набросал.

Странно вобще-то... Не должно быть никаких ошибок в Get.

Попробуй переобъявить массив так...
ReDim Byt(1024)
а потом...
Byt = String(1024, " ")

"..при помощи одного вызова get весь массив не заполнить.." - ошибаешься! Как раз все должно быть ок...

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Передача бинарных файлов через винсок

Сообщение awl100Alex » 19.11.2008 (Ср) 23:49

Кстати, ты проверь чтобы в..
Open a For Binary As #1
а - был передан файл, а не открыт пустой в каком-нибудь каталоге - такое тоже бывает! :(

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Передача бинарных файлов через винсок

Сообщение iGrok » 19.11.2008 (Ср) 23:53

viewtopic.php?f=1&t=38000
Особенно последние посты.

З.Ы. Массив из 1024 string'ов - это сильно. Я в той теме, конечно, тоже хорош.. Но это - сильно. =)
label:
cli
jmp label

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Передача бинарных файлов через винсок

Сообщение awl100Alex » 20.11.2008 (Чт) 0:04

iGrok
"...Массив из 1024 string'ов - это сильно..." - не совсем понял. Что ты этим хотел сказать???

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Передача бинарных файлов через винсок

Сообщение iGrok » 20.11.2008 (Чт) 0:22

awl100Alex писал(а):iGrok
"...Массив из 1024 string'ов - это сильно..." - не совсем понял. Что ты этим хотел сказать???

Сорри, привиделось. =)
Всё из-за этой строки:
awl100Alex писал(а):Byt = String(1024, " ")


Тем не менее.. Зачем вот это?
Код: Выделить всё
ReDim Byt(1024)
а потом...
Byt = String(1024, " ")

Что ты получишь в итоге?
label:
cli
jmp label

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Передача бинарных файлов через винсок

Сообщение awl100Alex » 20.11.2008 (Чт) 0:26

Я не знаю почему глючит прога у CapsLock. А это... - просто эксперимент...
Ну, первое что пришло на ум вот и все.

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Передача бинарных файлов через винсок

Сообщение iGrok » 20.11.2008 (Чт) 0:45

awl100Alex писал(а):Я не знаю почему глючит прога у CapsLock. А это... - просто эксперимент...
Ну, первое что пришло на ум вот и все.

Ааа.. Тогда понятно. Ты просто попробуй ради интереса это сделать, и посмотри, что получишь в итоге.. Забавная штука, надо сказать.. =)
label:
cli
jmp label

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Передача бинарных файлов через винсок

Сообщение awl100Alex » 20.11.2008 (Чт) 22:23

CapsLock - ответ на твой вопрос практически найден!
Практически, потому что не все так просто. Вот примеры кода «Клиент-Сервер» по передаче бинарных файлов. Сразу хочу подчеркнуть – у меня все работает отлично! :) Переданные файлы открываются и читаются без всяких проблем! Но(!) – все же в этих кодах не всех «жуков» удалось вытравить. :( Файлы больших размеров (например фильм – 700 МБайт) таким способом все равно не передаются. Почему? Не знаю... :( А во остальном, все работает. Проверено!

Server...
Код: Выделить всё
Const HWND_TOPMOST As Long = -&H1
Const SWP_NOSIZE As Long = &H1
Const SWP_NOMOVE As Long = &H2
Private Declare Function SetWindowPos Lib "user32" _
(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long

Dim Buffer() As Byte 'Создаем динамический массив...

Private Sub Form_Load()
'Устанавливаем форму "Поверх всех..." - просто для удобства. :)
SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE
'Запускаем прослушку порта...
tcpServer.LocalPort = 1001
tcpServer.Listen
End Sub

Private Sub tcpServer_ConnectionRequest(ByVal requestID As Long)
'Если соединение установилось...
If tcpServer.State <> sckClosed Then tcpServer.Close
tcpServer.Accept requestID 'Получаем ID соединения
fNum = FreeFile
'Открываем бинарный файл для чтения...
'Open App.Path & "\" & "01.mpg" For Binary Access Read As fNum             '19,6 МБайт
'Open App.Path & "\" & "Transparent.rar" For Binary Access Read As fNum    '3,72 МБайт
'Open App.Path & "\" & "ccsetup208.exe" For Binary Access Read As fNum     '2,77 Мбайт
'Open App.Path & "\" & "91.jpg" For Binary Access Read As fNum             '1,50 Мбайт
'Open App.Path & "\" & "005_vika.jpg" For Binary Access Read As fNum       '1,21 Мбайт
'Open App.Path & "\" & "CR2.exe" For Binary Access Read As fNum            '884  Kбайт
Open App.Path & "\" & "TOTALCMD.EXE" For Binary Access Read As fNum        '817  Кбайт
'Open App.Path & "\" & "Звук Microsoft.wav" For Binary Access Read As fNum '132 КБайт
  ReDim Buffer(LOF(fNum) - 1) 'Переопределяем размер буфера в точности по размеру файла
   Get fNum, , Buffer() 'Читаем файл в массив
   tcpServer.SendData Buffer 'Отправляем пакет
Close fNum 'Закрываем...
  Label1.Caption = "Файл передан!"
End Sub


Client...
Код: Выделить всё
Dim fNum As Byte 'Свободный файловый номер
Dim Data() As Byte 'Создаем динамический массив...

Private Sub Command1_Click()
tcpClient.RemoteHost = "127.0.0.1" 'Внутренний IP текущей машины
tcpClient.RemotePort = "1001"
tcpClient.Connect
End Sub

Private Sub Form_Load()
  fNum = FreeFile
  'Открываем новый файл для записи полученых данных...
  'Только расширение меняйте в зависимоcти от формата
  'принимаемого файла в ходе экспериментов!!!
  Open App.Path & "\Copy_" & "NewFile.EXE" For Binary Access Write As fNum
End Sub

Private Sub tcpClient_DataArrival(ByVal bytesTotal As Long)
'Если получили пакет данных, начинаем обработку...
tcpClient.GetData Data, vbArray, bytesTotal
'Записываем пакет в новый файл, и закрываем его по завершении передачи...
If Data Then Put fNum, , Data Else Close fNum
'Можно и так - If bytesTotal Then Put fNum, , Data Else Close fNum
End Sub


Код работает следующим образом:

1) Открываете каждый проект в отдельной инструменталке (VB6).
2) Запускаете сначала Server.
3) Затем Client.
4) На форме Клиента нажимаем единственную кнопку.
5) Ждем, когда Server сообщит, что файл передан.

Результат...
Выбранный в Open (Server)... файл будет скопирован в корневой каталог проекта Client. Не забудьте менять расширение в зависимости от расширения передаваемого файла!
Вот и все! :) Надеюсь, это тебе поможет. Удачи! :)
Вложения
Project (WinSock - бинарные файлы по сети).rar
Проект разработки...
(770.75 Кб) Скачиваний: 116
Последний раз редактировалось awl100Alex 21.11.2008 (Пт) 22:21, всего редактировалось 1 раз.

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Передача бинарных файлов через винсок

Сообщение iGrok » 21.11.2008 (Пт) 1:33

Ну так зачем такие файлы-то цеплять? И нафига ты туда на 4 метра бинарников напихал? Неужто у кого-то своих не найдётся? =)

Это, кстати, не загадки. Ты вот даже не проверил, что получается при выполнении Byt = String(1024, " ")..
А получается массив в 2048 байт, заполненный поочерёдно символами байтами 32 и 0. Догадываешься, почему?

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

Опять же, я писал, что надо читать "особенно последние посты". Там tyomitch писал, что можно отправлять файл целиком. Правду писал. Чистую. =)
Кстати говоря, засчёт того, что у тебя получается массив не 8к, а 16к, ты всё равно вылезаешь за указанные тобой пределы буфера WinSock. Но почему-то всё работает.. =)

Ну а если уж ты отправляешь его кусками - корректируй размер последнего куска. Иначе у тебя файл приходит большего размера, чем был. =)
Пример я не качал, но есть предположение, что размер полученного файла кратен 16384, сколько бы ни отправлялось.
label:
cli
jmp label

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Передача бинарных файлов через винсок

Сообщение awl100Alex » 21.11.2008 (Пт) 22:30

iGrok писал(а):Ты вот даже не проверил, что получается при выполнении Byt = String(1024, " ")..


Проверил... и давно знаю. Это связано с тем, что VB хранит строки в UniCode – 16 бит, а не 8 на один символ. В данном случаи это НЕ имеет никакого значения. Потому, что при чтении бинарных данных в строку VB автоматически производит конвертирование. Поэтому ты прав: размер буфера WinSock действительно превышается и это натолкнуло на мысль... За что спасибо, но об этом ниже...

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


Это не моя личная прихоть. Так указано в MSDN! Все вопросы лично Биллу Гейтсу – пришли ему на e-mail. ;)

Ну а если уж ты отправляешь его кусками - корректируй размер последнего куска. Иначе у тебя файл приходит большего размера, чем был. =)


В конец того или иного переданного файла просто дописываются нули, которые абсолютно никак(!) НЕ сказываются на его работе в итоге. Я пробовал копировать и архивы (RAR) и видео-файлы, EXE, инсталлы, картинки – все что попадалось... Все(!) файлы читались, распаковывались, воспроизводились БЕЗ ПРОБЛЕМ! :) Критичным к своему размеру оказался только Total Commander – у него противовирусный иммунитет встроен в exe-шник, видимо проверяющий контрольную сумму. Но это единичный частный случай.

tyomitch писал, что можно отправлять файл целиком


tyomitch был прав, только НЕ прав, что просто писал, а не показал, как...
Теперь ясно, что код можно оптимизировать и упростить еще больше, что сейчас и сделаю... но все равно: файлы больших размеров (например фильм – 700 МБайт) таким способом НЕ передаются. :(
iGrok
И в твоем, кстати, примере из предыдущего топика, что ты указал ссылкой, тоже самое... Пробовал передать фильм, а пришло всего 20 МБайт и те НЕ воспроизводятся! :(

P.S.
После такой... поправки кода Server’a, нормально заработал даже Total Commander. :)
Последний раз редактировалось awl100Alex 22.11.2008 (Сб) 0:22, всего редактировалось 1 раз.

CapsLock
Начинающий
Начинающий
 
Сообщения: 10
Зарегистрирован: 16.11.2008 (Вс) 23:42

Re: Передача бинарных файлов через винсок

Сообщение CapsLock » 21.11.2008 (Пт) 23:41

Total Commander
что это?

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Передача бинарных файлов через винсок

Сообщение awl100Alex » 22.11.2008 (Сб) 0:06

"TOTALCMD.EXE" - Total Commander... Который, в качестве примера, копируется... Что не понятного? Смотри исходник и пробуй.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 66

    TopList