Показаны различия между двумя версиями страницы.
Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
develop:qt:network [2021/09/30 09:03] admin |
develop:qt:network [2021/10/27 04:33] (текущий) admin |
||
---|---|---|---|
Строка 379: | Строка 379: | ||
===== Еще пример клиент/ | ===== Еще пример клиент/ | ||
- | В данном примере изменен подход: | + | Сервер поддерживает **множественное подключение**, для **каждого соединения** создается |
+ | При передаче, | ||
+ | **Программные** формируются при каждом вызове метода **write()**, | ||
- | < | + | **Физические** формируются уже на транспортном уровне, чаще всего для них отводится 65 536 байт (его |
- | < | + | |
- | sserv.h | + | |
- | <code cpp-qt> | + | |
- | #ifndef SSERV_H | + | |
- | #define SSERV_H | + | |
- | #include < | + | Передача ведется потоковая, |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | class sserv : public QDialog | + | Служебную инфу пишем с помощью датаСтрим, |
- | { | + | |
- | Q_OBJECT | + | |
- | QTcpServer *tcpServer; | + | Cчитывание 4ех байт остается корректным до тех пор пока программный пакет < 4gb, т.к. в эти 4 байта умещено интовое значение, |
- | | + | Если программный пакет будет больше, |
- | QLabel *labPort; | + | |
- | QLineEdit *editPort; | + | |
- | QTextEdit *editEventsLog; | + | |
- | private slots: | + | < |
- | void slotSetNewConnection(); | + | < |
- | void slotReadDataFromClient(); | + | |
- | void slotStartStop(int); | + | |
- | public: | ||
- | sserv(QWidget *parent = nullptr); | ||
- | }; | + | sserv.h |
- | #endif // SSERV_H | + | <code cpp-qt> |
</ | </ | ||
sserv.cpp | sserv.cpp | ||
<code cpp-qt> | <code cpp-qt> | ||
- | #include " | ||
- | sserv:: | ||
- | { | ||
- | this-> | ||
- | |||
- | checkRunning= new QCheckBox(" | ||
- | labPort= new QLabel(" | ||
- | editPort= new QLineEdit(" | ||
- | editEventsLog= new QTextEdit(this); | ||
- | editEventsLog-> | ||
- | |||
- | QGridLayout *layMain= new QGridLayout(this); | ||
- | layMain-> | ||
- | layMain-> | ||
- | layMain-> | ||
- | layMain-> | ||
- | layMain-> | ||
- | layMain-> | ||
- | |||
- | tcpServer= new QTcpServer(this); | ||
- | connect(tcpServer, | ||
- | connect(checkRunning, | ||
- | } | ||
- | |||
- | |||
- | void sserv:: | ||
- | { | ||
- | QTcpSocket *vNewConnect= tcpServer-> | ||
- | connect(vNewConnect, | ||
- | connect(vNewConnect, | ||
- | editEventsLog-> | ||
- | } | ||
- | |||
- | |||
- | void sserv:: | ||
- | { | ||
- | QTcpSocket *vConnect= static_cast< | ||
- | QDataStream vInput(vConnect); | ||
- | vInput.setVersion(QDataStream:: | ||
- | |||
- | QByteArray vFirstStr; | ||
- | vInput >> vFirstStr; | ||
- | |||
- | // Предполагалось тут считывать тоже через поток, но можно и так тоже | ||
- | QByteArray vBuffer; | ||
- | vBuffer= vConnect-> | ||
- | |||
- | QFile vFile(" | ||
- | vFile.open(QIODevice:: | ||
- | vFile.write(vBuffer); | ||
- | vFile.close(); | ||
- | } | ||
- | |||
- | |||
- | void sserv:: | ||
- | { | ||
- | switch(vState) | ||
- | { | ||
- | case Qt:: | ||
- | editPort-> | ||
- | if(!tcpServer-> | ||
- | editEventsLog-> | ||
- | else | ||
- | editEventsLog-> | ||
- | break; | ||
- | case Qt:: | ||
- | tcpServer-> | ||
- | editPort-> | ||
- | editEventsLog-> | ||
- | break; | ||
- | default: | ||
- | editEventsLog-> | ||
- | break; | ||
- | } | ||
- | } | ||
</ | </ | ||
</ | </ | ||
Строка 511: | Строка 411: | ||
< | < | ||
< | < | ||
- | sc.h | + | **Примечания: |
- | <code cpp-qt> | + | :?: Установка соединения (**connectToHost()**) проходит асинхронно, |
- | #ifndef SC_H | + | Правда в случае ошибки соединения, |
- | #define SC_H | + | :?: Запись можно делать из файла сразу в метод **write()**, |
+ | **write()** принимает **QByteArray**, | ||
+ | :?: Что касается **проверки и установления** коннекта: | ||
+ | в нашем случае сокет может быть в след состояниях: | ||
+ | **0** - не подключен - нужно **вызвать коннект**\\ | ||
+ | **1,2** - выполняет поиск и начал устанавливать соединение - соединения еще нет, но и делать вроде ничего не надо, правда неизвестно может ли оно быть зависшим в этот состоянии ?, думаю тут- **ничего не делать**\\ | ||
+ | **3** - установленно - **ничего не делать**\\ | ||
+ | **6** - вот вот закроется - т.е. запрошен дисконнект, | ||
- | #include < | + | Что касается отправки файла, пишем данные кусками в метод **write()**, |
- | #include < | + | В случае ошибки, |
- | #include < | + | Так же, после вызова **write()** и до фактической отправки данных нужно какое то время, до этого данные копятся в буфере (видно в **bytesToWrite()**), |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | class sc : public QDialog | + | Данные **пишутся** так же **пакетами**, |
- | { | + | Если нет коннекта, |
- | Q_OBJECT | + | |
- | QLabel *labPortServ; | ||
- | QLineEdit *editPort; | ||
- | QPushButton *butSendFile, | ||
- | QTextEdit *editEventsLog; | ||
- | QTcpSocket *tcpSocket; | ||
- | private slots: | ||
- | void slotDisplayError(QAbstractSocket:: | ||
- | void slotSendFile(); | ||
- | void slotConNocon(); | ||
- | void slotChangeState(QAbstractSocket:: | ||
- | public: | + | sc.h |
- | | + | <code cpp-qt> |
- | }; | + | |
- | #endif // SC_H | + | |
</ | </ | ||
sc.cpp | sc.cpp | ||
<code cpp-qt> | <code cpp-qt> | ||
- | #include " | ||
- | sc:: | + | </ |
- | { | + | </ |
- | this->setFont(QFont(" | + | |
- | QGridLayout *layMain= new QGridLayout(this); | ||
- | layMain-> | ||
- | layMain-> | ||
- | labPortServ= new QLabel(" | ||
- | editPort= new QLineEdit(" | ||
- | butConnectToServ= new QPushButton(" | ||
- | butSendFile= new QPushButton(" | ||
- | editEventsLog= new QTextEdit(this); | ||
- | editEventsLog-> | ||
- | layMain-> | ||
- | layMain-> | ||
- | layMain-> | ||
- | layMain-> | ||
- | layMain-> | ||
- | tcpSocket= new QTcpSocket(this); | ||
- | connect(tcpSocket, | ||
- | connect(butConnectToServ, | ||
- | connect(butSendFile, | ||
- | connect(tcpSocket, | ||
- | } | ||
- | |||
- | void sc:: | ||
- | { | ||
- | QFile vFile(" | ||
- | vFile.open(QIODevice:: | ||
- | QByteArray vBuffer; | ||
- | |||
- | QDataStream vOut(& | ||
- | vOut.setVersion(QDataStream:: | ||
- | vOut << " | ||
- | vOut << vFile.readAll(); | ||
- | |||
- | tcpSocket-> | ||
- | editEventsLog-> | ||
- | } | ||
- | |||
- | |||
- | void sc:: | ||
- | { | ||
- | if(tcpSocket-> | ||
- | { | ||
- | tcpSocket-> | ||
- | tcpSocket-> | ||
- | } | ||
- | else if (tcpSocket-> | ||
- | { | ||
- | tcpSocket-> | ||
- | tcpSocket-> | ||
- | } | ||
- | } | ||
- | |||
- | |||
- | void sc:: | ||
- | { | ||
- | switch (vSocket) | ||
- | { | ||
- | case QAbstractSocket:: | ||
- | editEventsLog-> | ||
- | break; | ||
- | case QAbstractSocket:: | ||
- | editEventsLog-> | ||
- | break; | ||
- | case QAbstractSocket:: | ||
- | editEventsLog-> | ||
- | break; | ||
- | case QAbstractSocket:: | ||
- | editEventsLog-> | ||
- | break; | ||
- | case QAbstractSocket:: | ||
- | editEventsLog-> | ||
- | break; | ||
- | case QAbstractSocket:: | ||
- | editEventsLog-> | ||
- | break; | ||
- | case QAbstractSocket:: | ||
- | editEventsLog-> | ||
- | break; | ||
- | } | ||
- | } | ||
- | |||
- | |||
- | void sc:: | ||
- | { | ||
- | editEventsLog-> | ||
- | } | ||
- | </ | ||
- | </ | ||