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

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


develop:qt:network

Различия

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

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

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
develop:qt:network [2021/09/30 04:49]
admin
develop:qt:network [2021/10/27 04:33] (текущий)
admin
Строка 8: Строка 8:
  
 ===== QTcpServer ===== ===== QTcpServer =====
------ 
 Позволяет принимать Tcp-соединения, порт можно выбрать либо авто, IP так же можно выбрать конкретный либо все IP хоста.\\ Позволяет принимать Tcp-соединения, порт можно выбрать либо авто, IP так же можно выбрать конкретный либо все IP хоста.\\
  
Строка 20: Строка 19:
  
 ===== QAbstractSocket ===== ===== QAbstractSocket =====
------ 
 {{ :develop:qt:qnet_0.png?direct&300|}} {{ :develop:qt:qnet_0.png?direct&300|}}
  
Строка 90: Строка 88:
  
 ===== Пример клиент/сервера ===== ===== Пример клиент/сервера =====
- 
-**upd:** В данном примере нужно организовать передачу служебной инфы.\\ 
-Есть примеры в которых передают инфу через **QDataStream** и пишут эти данные, вместе с файлом, в этот поток.\\ 
-В объекте потока есть (унаследованный) метод **seek()**, который управляет указателем в файле...\\ 
- 
  
 ==== Сервер ==== ==== Сервер ====
Строка 382: Строка 375:
 </code> </code>
 </details> </details>
 +
 +
 +
 +===== Еще пример клиент/сервера =====
 +Сервер поддерживает **множественное подключение**, для **каждого соединения** создается **собственный контекст**, с собственными **буферами**\\
 +
 +При передаче, данные делятся на пакеты дважды, типа программные и физические.\\
 +**Программные** формируются при каждом вызове метода **write()**, если писать через **QDataStream** в **QByteArray**, то перед каждой записью в датастрим будет автоматом добавлено интовое значение, с указанием размера записываемых данных.\\
 +
 +**Физические** формируются уже на транспортном уровне, чаще всего для них отводится 65 536 байт (его размер хранится в двухбайтовом поле заголовка т.е. само это поле может содержать максимум такое значение), размер может меняться по согласованию сторон, содержится в TCP заголовках.\\
 +
 +Передача ведется потоковая, сначала идет служебная инфа, с указанием размера в т.ч., затем все остальное принимаем как содержимое файла, пока не достигнем указанный размер файла.\\
 +
 +Служебную инфу пишем с помощью датаСтрим, что бы был указан размер этого "программного" пакета, и чтобы нам вырезать точное кол-во байт, занимаемое этой служебной инфой, содержимое файла просто читаем пока не достигнем указанного размера.\\
 +
 +Cчитывание 4ех байт остается корректным до тех пор пока программный пакет < 4gb, т.к. в эти 4 байта умещено интовое значение, которое принимает максимум 4 млрд.. байтов ~ 4gb.\\
 +Если программный пакет будет больше, мы просто некорректно считаем значение его размера и следовательно сам пакет не сможем принять (будет '-1')\\
 +
 +<details>
 +<summary>:!: Пример: Сервер</summary>
 +
 +
 +sserv.h
 +<code cpp-qt>
 +
 +</code>
 +
 +sserv.cpp
 +<code cpp-qt>
 +
 +</code>
 +</details>
 +
 +
 +<details>
 +<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>
 +</details>
 +
 +
 +
 +
  
  
develop/qt/network.1632977379.txt.gz · Последнее изменение: 2021/09/30 04:49 — admin