С Новым годом! Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.68/41: Рейтинг темы: голосов - 41, средняя оценка - 4.68
2 / 2 / 1
Регистрация: 08.09.2014
Сообщений: 117
1

Передача файла через QUdpSocket

07.12.2015, 14:12. Показов 7841. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, не могу наладить передачу файлов через UdpSocket, в Qt новичок, поэтому заранее прошу прощения вот код:
Server:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
QUdpSocket*udpSocket=new QUdpSocket(this)
 
void Server::slotSendToFile()
{
 QString fileName=QFileDialog::getOpenFileName(this,tr("Open File"),"",tr("Text Files(*.txt);;JPG Files(*.jpg)"));
    if (fileName!="") {
     QFile File(fileName);
     if (!File.open(QIODevice::ReadOnly)){
         QMessageBox::information(this,"Error", "File no correct");
 
     }
    QByteArray arr;
     QDataStream out(&arr, QIODevice::WriteOnly);
     out.setVersion(QDataStream::Qt_4_8);
     QByteArray buffer=File.readAll();
    out<<File.size();
    out<<buffer;
    udpSocket->writeDatagram(arr, QHostAddress::LocalHost, lePort->text().toInt());
    udpSocket->flush();
client:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
QUdpSocket*udpSocket=new QUdpSocket(this);
QTextEdit* te=new QTextEdit;
 
void Client::slotReadFile()
{
    QString fileName=QFileDialog::getSaveFileName(this,tr("Save File"),"",tr("Text Files(*.txt);;JPG Files(*.jpg)"));
    if (fileName!="") {
     QFile File(fileName);
     if (!File.open(QIODevice::ReadOnly)){
         QMessageBox::information(this,"Error", "File no correct");
 
     }
   QByteArray arr;
   do {
  arr.resize(udpSocket->pendingDatagramSize());
  udpSocket->readDatagram(arr.data(), arr.size());
   }
   while(udpSocket->hasPendingDatagrams());
   QDataStream in(&arr, QIODevice::ReadOnly);
   in.setVersion(QDataStream::Qt_4_8);
  in>>File;
   te->append("File read");
  }
 
}
Ошибок компилятор не выдает, но и файл не передает.
Я редко прошу помощи, но щас реально перерыл весь интернет, и еще дополнительный вопрос, не посоветуете какие обучающие сайты по Qt или книги, я пока сам читаю Макс Шлее -Профессиональное программирование
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
07.12.2015, 14:12
Ответы с готовыми решениями:

Передача массива по QUdpSocket
Доброго времени суток. Сначала я создаю и заполняю список структур, далее я записываю его в...

QUdpSocket - чат не работает через Интернет
Вообщем написал такой чатик на QUdpSocket, порт 12345 Вначале QLineEdit с ip по которому всё...

Передача массива через POST и подгрузка файла через AJAX
Доброго времени суток. Задача такого : есть элемент select в котором можно выбрать несколько...

Передача файла через сокеты
Столкнулся со следующей проблемой: передаю файл с клиента на линуксе на сервер на винде. Файл...

10
Эксперт С++
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.12.2015, 14:28 2
Недавно разбирался с QUdpSocket.
Во-первых стоит для начала разобраться с самим протоколом UDP, хотя бы прочесть википедию или доку Qt, и обратить внимание на ограничение макс размера датаграммы.
Во-вторых от размера датаграммы интенсивности передачи следует настраивать/подбирать размер буфера на приемной стороне, иначе пакеты могут теряться.

Я делал это с помощью функции (некроссплатформенным способом)

*.pro
C++ (Qt)
1
2
3
win32|win64{
  LIBS+= -lws2_32
}
*.cpp
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifdef Q_OS_WIN
  #include <WinSock2.h>
#else
  #include <sys/types.h>
  #include <sys/socket.h>
#endif
 
bool setReadBufferSize(QUdpSocket* socket,int size)
{
#ifdef Q_OS_WIN
   return ::setsockopt(socket->socketDescriptor(),
                 SOL_SOCKET,
                 SO_RCVBUF,
                 (char *)&size,
                 sizeof(size))  != -1;
#else
  return ::setsockopt(socket->socketDescriptor(),
                 SOL_SOCKET,
                 SO_RCVBUF,
                 (char *)&size,
               sizeof(size))    != -1;
#endif
}
Под виндой работало, под Debian Linux почему то не давало результата.
0
2 / 2 / 1
Регистрация: 08.09.2014
Сообщений: 117
07.12.2015, 14:55  [ТС] 3
Сейчас как раз разбираюсь с UdpSocket ,ваш пример все же отличается от того что я находил, но все равно спасибо щас попробую, только еще вопрос, как вы реализовывайте передачу файла со стороны которая передает файл?
0
Эксперт С++
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.12.2015, 14:59 4
Это не пример, это лишь функция которая изменяет буфер для чтения.
В вашем случае нужно определится с размерам датаграммы, и при отсылки делить файл на части и пересылать частями, т.е нужно будет делать <размер файла>/<размер датаграммы> "посылок".
Кроме того исходя из протокола UDP датаграммы могут приходить в произвольном порядке поэтому стоит каждую датаграмму снабжать ее номером, что бы на приеме можно было потом отсортировать датаграммы и склеить все в правильном порядке.
1
2 / 2 / 1
Регистрация: 08.09.2014
Сообщений: 117
07.12.2015, 15:04  [ТС] 5
Проще говоря, нужно дробить файл и пересылать его по частям, ну вроде максимальный размер датаграммы около 65 килобайт, наверное буду пробовать с таким размером.
0
Эксперт С++
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.12.2015, 15:34 6
Цитата Сообщение от unlimeted Посмотреть сообщение
ну вроде максимальный размер датаграммы около 65 килобайт, наверное буду пробовать с таким размером.
На локальной машине под виндовс скорее всего будет работать, в реальной сети могут возникнуть проблемы.

Длина посылки

Поле, задающее длину всей датаграммы (заголовка и данных) в байтах. Минимальная длина равна длине заголовка — 8 байт. Теоретически, максимальный размер поля — 65535 байт для UDP-датаграммы (8 байт на заголовок и 65527 на данные). Фактический предел для длины данных при использовании IPv4 — 65507 (помимо 8 байт на UDP-заголовок требуется ещё 20 на IP-заголовок).

На практике также следует учитывать, что если длина IPv4 пакета с UDP будет превышать MTU (для Ethernet по умолчанию 1500 байт), то отправка такого пакета может вызвать его фрагментацию, что может привести к тому, что он вообще не сможет быть доставлен, если промежуточные маршрутизаторы или конечный хост не будут поддерживать фрагментированные IP пакеты. Также в RFC791 указывается минимальная длина IP пакета 576 байт, которую должны поддерживать все участники, и рекомендуется отправлять IP пакеты большего размера только в том случае если вы уверены, что принимающая сторона может принять пакеты такого размера. Следовательно, чтобы избежать фрагментации UDP пакетов (и возможной их потери), размер данных в UDP не должен превышать: MTU — (Max IP Header Size) — (UDP Header Size) = 1500 — 60 — 8 = 1432 байт. Для того чтобы быть уверенным, что пакет будет принят любым хостом, размер данных в UDP не должен превышать: (минимальная длина IP пакета) — (Max IP Header Size) — (UDP Header Size) = 576 — 60 — 8 = 508 байт .
https://ru.wikipedia.org/wiki/... 0.BA.D0.B8
0
2 / 2 / 1
Регистрация: 08.09.2014
Сообщений: 117
07.12.2015, 15:40  [ТС] 7
А не знаете есть ли еще какие нибуть средства передачи файлов в Qt? И что вообще лучше изучать для данного вопроса?
0
Эксперт С++
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.12.2015, 15:41 8
Цитата Сообщение от unlimeted Посмотреть сообщение
А не знаете есть ли еще какие нибуть средства передачи файлов в Qt? И что вообще лучше изучать для данного вопроса?
А почему не передавать файлы по TCP?
Для передачи файлов обычно используют FTP, но в Qt есть только клиент, сервер же вероятно придется писать либо самому либо искать в интернете исходники/либы.
0
2 / 2 / 1
Регистрация: 08.09.2014
Сообщений: 117
07.12.2015, 15:49  [ТС] 9
Я это делал вот:
client

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void MyClient::sendToFile()
{
   QString fileName=QFileDialog::getOpenFileName(this,tr("Open File"),"",tr("JPG Files(*.jpg)"));
   if (fileName!="") {
    QFile File(fileName);
    if (!File.open(QIODevice::ReadOnly)){
        QMessageBox::information(this,"Error", "File no correct");
 
    }
   QByteArray arr;
    QDataStream out(&arr, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_8);
   // QFile File(fileName);
   // File.open(QIODevice::ReadOnly);
    QByteArray buffer=File.readAll();
    out<<quint64(File.size());
    out<<buffer;
    tcpSocket->write(arr);
    tcpSocket->flush();
 
}
server:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// QTcpSocket*socket=static_cast<QTcpSocket*>(sender());
 QString fileName=QFileDialog::getSaveFileName(this, tr("Save File"),"",tr("JPG Files(*.jpg)"));
 if (fileName!="") {
     QFile File(fileName);
     if (!File.open(QIODevice::WriteOnly)){
         QMessageBox::information(this,"Error", "File no correct");
    }
     else
     {
 
 forever
 {
     QDataStream out(tcpSocket_2);
     out.setVersion(QDataStream::Qt_4_8);
     if (m_nextBlockSize==0){
         if (tcpSocket_2->bytesAvailable()<sizeof(quint64))
             return;
         out>>m_nextBlockSize;
 
     }
     if (m_nextBlockSize>tcpSocket_2->bytesAvailable())
         return;
     QByteArray arr;
     out>>arr;
    // QFile File("C:\\log.jpg");
    // File.open(QIODevice::WriteOnly);
     File.write(arr);
     m_nextBlockSize=0;
 }
     }
 
 
 }
Только столкнулся с такой проблемой, мне нужно чтобы клиент и сервер обменивались и сообщениями и файлами, но когда я присоединил к одному сигналу(ReadyRead) сразу 2 слота с принятием фалов и сообщений получается фигня, вариант только не спрашивать куда нужно сохранять файл, а задать путь сразу, а я пока так не хочу, я думал передавать сообщения через TCP, а файлы через Udp


 Комментарий модератора 

Используйте теги для вставки кода в свои сообщения!
0
Эксперт С++
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
07.12.2015, 15:53 10
Цитата Сообщение от unlimeted Посмотреть сообщение
я думал передавать сообщения через TCP, а файлы через Udp
В этом нет нужны.
Следует разработать протокол общения. Т.е формат сообщений в котором будет указываться какой это тип сообщения текст или файл что бы приемная сторона знала как работать с принимаемыми файлами.
В крайнем случае можно создавать по паре сокетов с разными портами.
0
2 / 2 / 1
Регистрация: 08.09.2014
Сообщений: 117
07.12.2015, 20:25  [ТС] 11
Я думал над этим, но знаний пока не хватает как это сделать, поэтому и пробую все варианты, и поэтому спрашивал в самом начале, про книги и сайты по обучению в Qt

Добавлено через 4 часа 29 минут
А вот на счет разных портов я как то не подумал, попробовал, получилось, спасибо большое!)))
0
07.12.2015, 20:25
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.12.2015, 20:25
Помогаю со студенческими работами здесь

Передача файла через TCP
Как файл передавать с клиента на сервер я знаю, но мне нужно условие такое &quot;Работа с файлами с...

Передача файла через сокет
Проблема в том что файл восстанавливаемый на клиенте открывается хорошо. На сервере же массив...

Передача файла через сокеты
Добрый вечер. Столкнулся с задачей, которая звучит так: написать клиент-серверное приложение,...

Передача файла через SocketChannel
Всем привет. Наверняка кто-нибудь сталкивался с такой задачей: нужно передать файл через сокетное...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Как написать микросервис на Go/Golang
InfoMaster 14.01.2025
Определение микросервиса, преимущества использования Go/ Golang Микросервис – это архитектурный подход к разработке программного обеспечения, при котором приложение состоит из небольших, независимо. . .
Как написать микросервис с нуля на C#
InfoMaster 14.01.2025
В современном мире разработки программного обеспечения микросервисная архитектура стала стандартом де-факто для создания масштабируемых и гибких приложений. Этот архитектурный подход предполагает. . .
Как создать интернет-магазин на PHP и JavaScript
InfoMaster 14.01.2025
В современном мире электронная коммерция стала неотъемлемой частью бизнеса. Создание собственного интернет-магазина открывает широкие возможности для предпринимателей, позволяя достичь большей. . .
Как написать Тетрис на Ассемблере
InfoMaster 14.01.2025
Тетрис – одна из самых узнаваемых и популярных компьютерных игр, созданная в 1984 году советским программистом Алексеем Пажитновым. За прошедшие десятилетия она завоевала симпатии миллионы людей по. . .
Как создать игру "Танчики" на Unity3d и C#
InfoMaster 14.01.2025
Разработка игр – это увлекательный процесс, сочетающий в себе творчество и технические навыки. В этой статье мы рассмотрим создание классической игры "Танчики" с использованием Unity3D и языка. . .
Организую платный онлайн микро-курс по доработке Android-клиента Telegram
_Ivana 14.01.2025
Официальная версия и распространенные форки не полностью устраивают? Сделай свою кастомную версию клиента! 4 занятия по 2 часа (2 недели пн, ср 19:00-21:00 по Москве). Первое вводное занятие. . .
Как создать приложение для фитнеса для iOS/iPhone на Kotlin
InfoMaster 14.01.2025
Создание собственного фитнес-приложения — это не только захватывающий, но и полезный процесс, ведь оно может стать вашим верным помощником на пути к здоровому и активному образу жизни. В современных. . .
Как создать приложение магазина для iOS/iPhone на Swift
InfoMaster 14.01.2025
Введение в разработку iOS-приложений Разработка приложений для iPhone и других устройств на базе iOS открывает огромные возможности для создания инновационных мобильных решений. В данной статье мы. . .
Это работает. Скорость асинхронной логики велика. Вопрос видимо останется в стабильности. Плата - огонь!
Hrethgir 13.01.2025
По прошлому проекту в Logisim Evolution https:/ / www. cyberforum. ru/ blogs/ 223907/ blog8781. html прилагаю файл архива проекта в Gowin Eda. Восьмибитный счётчик из сумматора+ генератор сигнала. . .
UserScript для подсветки кнопок языков программировани­­­­я в зависимости от текущего раздела
volvo 13.01.2025
В результате работы этого скрипта подсвечиваются нужные кнопки не только в форме быстрого ответа, но и при редактировании сообщения: / / ==UserScript== / / @name CF_DefaultLangSelect / / . . .
Введение в модели и алгоритмы машинного обучения
InfoMaster 12.01.2025
Машинное обучение представляет собой одну из наиболее динамично развивающихся областей искусственного интеллекта, которая фокусируется на разработке алгоритмов и методов, позволяющих компьютерам. . .
Как на Python создать нейросеть для решения задач
InfoMaster 12.01.2025
В контексте стремительного развития современных технологий особое внимание уделяется таким инструментам, как нейросети. Эти структуры, вдохновленные биологическими нейронными сетями, используются для. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru