Инструменты пользователя

Инструменты сайта


develop:qt:network

Различия

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

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
develop:qt:network [2021/09/30 07:51]
admin
develop:qt:network [2021/10/27 04:33] (текущий)
admin
Строка 19: Строка 19:
  
 ===== QAbstractSocket ===== ===== QAbstractSocket =====
------ 
 {{ :develop:qt:qnet_0.png?direct&300|}} {{ :develop:qt:qnet_0.png?direct&300|}}
  
Строка 380: Строка 379:
  
 ===== Еще пример клиент/сервера ===== ===== Еще пример клиент/сервера =====
-В данном примере изменен подход: файл передается **от клиента серверу**, сервер почти поддерживает **множество клиентов** (создается объект сокета при каждом новом подключенииэтот вопрос еще нужно больше изучить), и главное то что **передается служебная инфа**, благодаря тому что чтение/запись ведется с помощью потоков данных (**QDataStream**).\\+Сервер поддерживает **множественное подключение**для **каждого соединения** создается **собственный контекст**, с собственными **буферами**\\
  
 +При передаче, данные делятся на пакеты дважды, типа программные и физические.\\
 +**Программные** формируются при каждом вызове метода **write()**, если писать через **QDataStream** в **QByteArray**, то перед каждой записью в датастрим будет автоматом добавлено интовое значение, с указанием размера записываемых данных.\\
 +
 +**Физические** формируются уже на транспортном уровне, чаще всего для них отводится 65 536 байт (его размер хранится в двухбайтовом поле заголовка т.е. само это поле может содержать максимум такое значение), размер может меняться по согласованию сторон, содержится в TCP заголовках.\\
 +
 +Передача ведется потоковая, сначала идет служебная инфа, с указанием размера в т.ч., затем все остальное принимаем как содержимое файла, пока не достигнем указанный размер файла.\\
 +
 +Служебную инфу пишем с помощью датаСтрим, что бы был указан размер этого "программного" пакета, и чтобы нам вырезать точное кол-во байт, занимаемое этой служебной инфой, содержимое файла просто читаем пока не достигнем указанного размера.\\
 +
 +Cчитывание 4ех байт остается корректным до тех пор пока программный пакет < 4gb, т.к. в эти 4 байта умещено интовое значение, которое принимает максимум 4 млрд.. байтов ~ 4gb.\\
 +Если программный пакет будет больше, мы просто некорректно считаем значение его размера и следовательно сам пакет не сможем принять (будет '-1')\\
  
 <details> <details>
 <summary>:!: Пример: Сервер</summary> <summary>:!: Пример: Сервер</summary>
 +
 +
 +sserv.h
 +<code cpp-qt>
 +
 +</code>
 +
 +sserv.cpp
 <code cpp-qt> <code cpp-qt>
  
Строка 393: Строка 411:
 <details> <details>
 <summary>:!: Пример: Клиент</summary> <summary>:!: Пример: Клиент</summary>
 +**Примечания:**\\
 +:?: Установка соединения (**connectToHost()**) проходит асинхронно, после ее вызова уже можно писать данные в сокет (**write()**), данные будут собираться в буфер (**неизвестно какое ограничение**), и будут ожидать записи.\\
 +Правда в случае ошибки соединения, буфер очистится, при проверке, данные были доступны вплоть до последнего сигнала об ошибке, при повторном запуске отправки, буфер уже был очищен.\\
 +:?: Запись можно делать из файла сразу в метод **write()**, без создания дополнительных **QByteArray** и **QDataStream**, как было в прошлых примерах.\\
 +**write()** принимает **QByteArray**, метод **read()** возвращает **QByteArray**, для записи служебных данных можно сделать отдельный метод для конвертации, вот тут та и понадобится **QDataStream**, который корректно запишет нужные данные в **QByteArray**.\\
 +:?: Что касается **проверки и установления** коннекта:\\
 +в нашем случае сокет может быть в след состояниях:\\
 +**0** - не подключен - нужно **вызвать коннект**\\
 +**1,2** - выполняет поиск и начал устанавливать соединение - соединения еще нет, но и делать вроде ничего не надо, правда неизвестно может ли оно быть зависшим в этот состоянии ?, думаю тут- **ничего не делать**\\
 +**3** - установленно - **ничего не делать**\\
 +**6** - вот вот закроется - т.е. запрошен дисконнект, ожидается отправка очереди данных и коннект захлопнется, в таком случае явно нужно снова **вызвать коннект**\\
 +
 +Что касается отправки файла, пишем данные кусками в метод **write()**, он возвращает кол-во записанных байт, это кол-во отнимаем от размера файла, так управляем циклом\\
 +В случае ошибки, **write()** возвращает **-1** и все идет по п#зде, поэтому необходимо проверять значение пред тем как с ним работать (отнимать от общем суммы)\\
 +Так же, после вызова **write()** и до фактической отправки данных нужно какое то время, до этого данные копятся в буфере (видно в **bytesToWrite()**), если писать в цикле то данные **не успевают** уходить в **заполняют буфер** до талого, поэтому нужен метод **wait()**, либо сигнало/слот можно прикрутить какой нибудь\\
 +
 +Данные **пишутся** так же **пакетами**, как были записаны в **write()**, по одному после каждого **wait()**\\
 +Если нет коннекта, данные не уходят, **bytesToWrite()** не очищается, последующие вызовы **write()** возвращают **-1**, **wait()** возвращает **false**\\
 +
 +
 +
 +sc.h
 +<code cpp-qt>
 +
 +</code>
 +
 +sc.cpp
 <code cpp-qt> <code cpp-qt>
  
 </code> </code>
 </details> </details>
 +
 +
 +
 +
 +
  
  
develop/qt/network.1632988303.txt.gz · Последнее изменение: 2021/09/30 07:51 — admin