Qt Network Explained (Portuguese)

  • 404 views
Uploaded on

Desenvolver uma aplicação que precisa de comunicar com a rede não precisa ser complicado. Neste webinar será mostrado como o Qt torna programação para rede muito mais simples. Será dado um rápido …

Desenvolver uma aplicação que precisa de comunicar com a rede não precisa ser complicado. Neste webinar será mostrado como o Qt torna programação para rede muito mais simples. Será dado um rápido overview de como criar sockets UDP e TCP, broadcast e multicast além de fazer requisições REST usando somente a API do QtNetwork.

More in: Technology , Education
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
404
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
4
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. ECOSYSTEM1 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 2. QtNetwork explained2 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 3. TÓPICOS • Introdução ao QtNetwork • Por que usar QtNetwork • Sockets ● QAbstractSocket ● QTcpSocket – QsslSocket ● QTcpServer ● QudpSocket – Broadcast – Multicast (somente 4.8 !symbian)3 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 4. TÓPICOS • High level networking ● QnetworkAccessManager ● QnetworkConfiguration ● QnetworkConfigurationManager ● QnetworkSession ● QnetworkRequest ● QNetworkReply4 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 5. Introdução ao QtNetwork • QtNetwork é um módulo do Qt • Provê uma interface cross platforma para escrever aplicações cliente servidor TCP/IP • Suporta proxy • Possui classes para realizar requests http e ftp, acessar web services e tratar suas respostas. • Pegar informações sobre dispositivos de rede • É possível ainda gerenciar o estado de conexão com a rede, ter configurações específicas para cada uma e realizar ações.
  • 6. Por que usar QtNetwork?int main(){ int main() int fd = socket(AF_INET, SOCK_STREAM, 0); { if (fd == 1) { QCoreApplication app(argc, argv); printf("can not create socket"); exit(1); } QTcpServer server; struct sockaddr_in saddr; bzero(&saddr, sizeof(saddr)); server.listen(QHostAddress::Any, 1100); saddr.sin_family = AF_INET; saddr.sin_port = htons(1100); saddr.sin_addr.s_addr = htonl(INADDR_ANY); while (server.waitForNewConnection()) { do { if (bind(fd,(struct sockaddr *)&saddr, sizeof(saddr)) == 1) { QTcpSocket *socket = server.nextPendingConnection(); printf("error bind failed"); socket->write(“Hello, world!”); exit(1); } socket->disconnectFromHost(); if (listen(fd, 10) == 1) socket->waitForDisconnected(); { delete socket; printf("error listen failed"); exit(1); } while (server.hasPendingConnections()); } } for(;;) { int connfd = accept(fd, NULL, NULL); } if(connfd <= 0) { printf("error accept failed"); exit(1); } write(connfd, "Hello world!n", 13); close(connfd); } return 0;}
  • 7. Sockets: QAbstractSocket • QabstractSocket é uma camada de abstração multi plataforma para api nativa de network • Implementa TCP, UDP e sockets locais • Herda de QIODevice7 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 8. Sockets: QTcpSocket ● Subclasse de conveniência do QAbstractSocket ● Pode ser utilizado pra implementar vários tipos protocolos ● Stream de dados contínuo ● Poder ser usado de maneira asíncrona ou síncrona.
  • 9. Sockets: QTcpSocket ClientSocket::ClientSocket(QObject *parent)ServerSocket::ServerSocket(QObject *parent) : QTcpSocket(parent) : QTcpSocket(parent) {{ connect(this, SIGNAL(readyRead()), connect(this, SIGNAL(readyRead()), this, SLOT(onReadyRead())); this, SLOT(onReadyRead()));} connect(this, SIGNAL(disconnected()),void ServerSocket::onServerInfoResponse(const QVariantMap &map) this, SLOT(onDisconnected()));{ QJson::Serializer serializer; connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError))); write(serializer.serialize(map)); } flush();} void ClientSocket::onDisconnected() {void ServerSocket::onServerStatusChanged(const QString &status) qDebug() << "[ClientSocket] Client disconnected!"; }{ QVariantMap map; void ClientSocket::onError(QAbstractSocket::SocketError error) map["what"] = "server"; { map["action"] = "statusChanged"; map["status"] = status; qDebug() << "[ClientSocket] Error: " << error; } QJson::Serializer serializer; write(serializer.serialize(map)); void ClientSocket::requestServerInfo() flush(); {} QVariantMap map; QJson::Serializer serializer;void ServerSocket::onReadyRead(){ while (canReadLine()) { map["what"] = "server"; QByteArray line = readLine(); map["action"] = "serverInfo"; write(serializer.serialize(map)"); bool parserOk = true; } QJson::Parser parser; void ClientSocket::onQJsonParsingFinished(const QVariant &json, bool ok, const QString &error_msg) QVariant var = parser.parse(line, &parserOk); { if (!parserOk) { if (!ok) { qWarning() qWarning() << Q_FUNC_INFO << "json error at" << error_msg; << Q_FUNC_INFO return; << "json error at" } << parser.errorLine() << parser.errorString(); QVariantMap map = json.toMap(); } else { QString what = map["what"].toString(); QVariantMap map = var.toMap(); if (what == "server") { QString what = map["what"].toString(); if (what == "server") { QString action = map["action"].toString(); QString action = map["action"].toString(); if (action == "serverInfo") { if (action == "info") { emit serverInfoReceived(map); emit serverInfoRequested(); } } } } } } }}
  • 10. Sockets: QTcpServer ● Precisa receber conexões? Essa é a classe certa. ● Pode ser single threaded or multi threaded ● Single threaded ● Um ou vários sockets usando mesmo Event loop ● Ou Bloqueante ● Multi threaded ● Um socket por thread – Bloqueante – Ou um Event loop por thread
  • 11. Sockets: QTcpServerServer::Server(QObject *parent) : QtcpServer(parent) , m_serverInfo(){}void Server::start(){ listen(QHostAddress::Any, 12345);}void Server::incomingConnection(int socketDescriptor){ ServerSocket *sock = new ServerSocket; sock->setSocketDescriptor(socketDescriptor); QThread *thread = new QThread; sock->moveToThread(thread); connect(sock, SIGNAL(disconnected()), sock, SLOT(deleteLater())); connect(sock, SIGNAL(destroyed()), thread, SLOT(quit())); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); connect(this, SIGNAL(statusChanged(const Qstring &)), sock, SLOT(onServerStatusChanged(const Qstring &))); connect(sock, SIGNAL(serverInfoRequested()), this, SLOT(onServerInfoRequested())); thread->start();}void Server::onServerInfoRequested(){ ServerSocket *sock = qobject_cast<ServerSocket*>(sender()); if (!sock) return; QMetaObject::invokeMethod(sock, "onServerInfoResponse", Q_ARG(QVariantMap, m_serverInfo));}
  • 12. Sockets: QudpSocket BroadcastBroadcastAnnounce::BroadcastAnnounce(QObject *parent) : QObject(parent) , m_socket(new QUdpSocket(this)) , m_timer(new QTimer(this)) , m_serverInfo(){ connect(m_timer, SIGNAL(timeout()), this, SLOT(sendDatagram()));}void BroadcastAnnounce::start(){ if (m_timer->isActive()) m_timer->stop(); m_timer->start(1000);}void BroadcastAnnounce::stop(){ m_timer->stop();}void BroadcastAnnounce::setServerInfo(const QVariantMap &map){ m_serverInfo = map;}void BroadcastAnnounce::sendDatagram(){ QByteArray datagram; QDataStream out(&datagram, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_4_7); out << QVariant(m_serverInfo); m_socket->writeDatagram(datagram.data(), datagram.size(), QHostAddress::Broadcast,UDP_PORT);}
  • 13. Sockets: QudpSocket BroadcastBroadcastAnnounce::BroadcastAnnounce(QObject *parent) BroadcastDiscover::BroadcastDiscover(QObject *parent) : QObject(parent) : QObject(parent) , m_socket() , m_timer(new QTimer(this)) , m_socket(new QUdpSocket(this)) { , m_timer(new QTimer(this)) connect(m_timer, SIGNAL(timeout()), this, SLOT(stop())); } , m_serverInfo(){ void BroadcastDiscover::start() { connect(m_timer, SIGNAL(timeout()), this, SLOT(sendDatagram())); m_socket = new QUdpSocket(this);} m_socket->bind(UDP_PORT, QUdpSocket::ShareAddress); connect(m_socket, SIGNAL(readyRead()), this, SLOT(processDatagrams()));void BroadcastAnnounce::start() m_timer->start(10000); }{ if (m_timer->isActive()) void BroadcastDiscover::stop() { m_timer->stop(); disconnect(m_socket, SIGNAL(readyRead()), this, SLOT(processDatagrams())); m_socket->close(); m_timer->start(1000); emit timeout();} } void BroadcastDiscover::processDatagrams()void BroadcastAnnounce::stop() { QUdpSocket *socket = qobject_cast<QUdpSocket *>(sender());{ if (!socket) m_timer->stop(); return;} while (socket->hasPendingDatagrams()) { QByteArray datagram;void BroadcastAnnounce::setServerInfo(const QVariantMap &map) QHostAddress host;{ datagram.resize(socket->pendingDatagramSize()); m_serverInfo = map; socket->readDatagram(datagram.data(), datagram.size(), &host);} QVariant message;void BroadcastAnnounce::sendDatagram() QDataStream dataStream(&datagram, QIODevice::ReadOnly);{ dataStream >> message; QByteArray datagram; const QVariantMap map = message.toMap(); QDataStream out(&datagram, QIODevice::WriteOnly); if (map["app_id"].toString() == APP_ID) { const QString action = map["action"].toString(); out.setVersion(QDataStream::Qt_4_7); if (action == "serverAnnounce") { out << QVariant(m_serverInfo); emit serverFound(map); } m_socket->writeDatagram(datagram.data(), datagram.size(), QHostAddress::Broadcast, }UDP_PORT); }} }
  • 14. Sockets: QudpSocket MulticastMulticastAnnounce::MulticastAnnounce(QObject *parent) MulticastDiscover::MulticastDiscover(QObject *parent) : QObject(parent) : QObject(parent) , m_socket() , m_socket(new QUdpSocket(this)) , m_timer(new QTimer(this)) { , m_timer(new QTimer(this)) connect(m_timer, SIGNAL(timeout()), this, SLOT(stop())); , m_serverInfo() }{ void MulticastDiscover::start() connect(m_timer, SIGNAL(timeout()), this, SLOT(sendDatagram())); { m_socket = new QUdpSocket(this); m_socket->setSocketOption(QAbstractSocket::MulticastTtlOption, 1); m_socket->bind(UDP_PORT, QUdpSocket::ShareAddress); m_socket->joinMulticastGroup(QHostAddress("239.255.43.21"));} connect(m_socket, SIGNAL(readyRead()), this, SLOT(processDatagrams()));void MulticastAnnounce::start() m_timer->start(10000);{ } if (m_timer->isActive()) void MulticastDiscover::stop() m_timer->stop(); { disconnect(m_socket, SIGNAL(readyRead()), this, SLOT(processDatagrams())); m_timer->start(1000); m_socket->close();} emit timeout(); }void MulticastAnnounce::stop() void MulticastDiscover::processDatagrams(){ { m_timer->stop(); QUdpSocket *socket = qobject_cast<QUdpSocket *>(sender()); if (!socket)} return; while (socket->hasPendingDatagrams()) {void MulticastAnnounce::setServerInfo(const QVariantMap &map) QByteArray datagram;{ QHostAddress host; m_serverInfo = map; datagram.resize(socket->pendingDatagramSize());} socket->readDatagram(datagram.data(), datagram.size(), &host);void MulticastAnnounce::sendDatagram() QVariant message; QDataStream dataStream(&datagram, QIODevice::ReadOnly); dataStream >> message;{ QByteArray datagram; const QVariantMap map = message.toMap(); if (map["app_id"].toString() == APP_ID) { QDataStream out(&datagram, QIODevice::WriteOnly); const QString action = map["action"].toString(); out.setVersion(QDataStream::Qt_4_8); if (action == "serverAnnounce") { out << QVariant(m_serverInfo); emit serverFound(map); } } m_socket->writeDatagram(datagram.data(), datagram.size(), QHostAddress("239.255.43.21"), UDP_PORT); } }}
  • 15. Sockets: QUdpSocket ● Subclasse de conveniência do QabstractSocket para UDP ● Envio de pacotes de dados ao invés de stream contínuo ● Possui suporte a Broadcast ● Desde o Qt 4.8 suporte a Multicast
  • 16. QnetworkConfigurationManager1- Definir o Ponto de AcessoQNetworkConfigurationManager manager;//Define que o usuário pode escolher um ponto de acessoconst bool canStartIAP = (manager.capabilities()&QnetworkConfigurationManager::CanStartAndStopInterfaces);//Retorna a configuração padrão atualmanager.defaultConfiguration(); 16 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 17. QnetworkConfiguration1- Definir o Ponto de AcessoQNetworkConfigurationManager manager;//Define que o usuário pode escolher um ponto de acessoconst bool canStartIAP = (manager.capabilities()&QNetworkConfigurationManager::CanStartAndStopInterfaces);//Se existe um ponto de acesso padrao. Basta utiliza-lo usandoa configuracao padrao do QNetWorkConfigurarionManagerQNetworkConfiguration cfg = manager.defaultConfiguration();if (!cfg.isValid() || !canStartIAP) {// Pontos de acesso nao encontrados ou impossivel seconectar// Alertar usuario e fazer tratamento de erroreturn;} 17 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 18. QnetworkSession// Caso a conexao tenha ocorrido com sucesso, abrir umQNetworkSession usando a configuracao padraom_session = new QNetworkSession(cfg);//Conectar sinais necessariosconnect(m_session, SIGNAL(closed()), this, SLOT(closed()));connect(m_session,SIGNAL(stateChanged(QNetworkSession::State)), this,SLOT(stateChanged(QNetworkSession::State)));connect(m_session,SIGNAL(error(QNetworkSession::SessionError)), this,SLOT(error(QNetworkSession::SessionError)));Abrir aconexaom_session->open();// Espera a sessão ser aberta e continua a partir daim_session->waitForOpened();Para fechar a sessão, usar o slot finished() 18 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 19. QnetworkAccessManager1- Criar um Network Access Managernam = new QNetworkAccessManager(this);2- Conectar o sinal finished a um slot para tratar o resultadoQObject::connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finishedSlot(QNetworkReply*))); 19 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 20. QnetworkRequest1- Criar um Network Access Managernam = new QNetworkAccessManager(this);2- Conectar o sinal finished a um slot para tratar o resultadoQObject::connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finishedSlot(QNetworkReply*)));3- Criar o RequestQUrl url(http://query.yahooapis.com/v1/public/yql);url.addQueryItem(QUERY_PARAM,QLatin1String("select+*+from+geo.placefinder+where+text="")+ "Sao Paulo" + QLatin1String("""));url.addQueryItem("format", "json");QnetworkRequest request(url); 20 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 21. QNetworkReply1- Criar um Network Access Managernam = new QNetworkAccessManager(this);2- Conectar o sinal finished a um slot para tratar o resultadoQObject::connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finishedSlot(QNetworkReply*)));3- Criar o RequestQUrl url(http://query.yahooapis.com/v1/public/yql);url.addQueryItem(QUERY_PARAM,QLatin1String("select+*+from+geo.placefinder+where+text="")+ "Sao Paulo" + QLatin1String("""));url.addQueryItem("format", "json");QnetworkRequest request(url);4- Guardar o reply do request par ser usado como identificador da respostaQNetworkReply* reply = nam->get(request) 21 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 22. QNetworkReply4- Tratar o Replyvoid MyHttpEngine::finishedSlot(QNetworkReply* reply) { // Ler Atributos do Repply como ocodigo de Status HTTP QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);void MyHttpEngine::finishedSlot(QNetworkReply* reply) { // Ler Atributos do Repply como o codigo de Status HTTP QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); // Ou a URL, se esta tiver sido redirecionada: QVariant redirectionTargetUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); // Verificar se houve erro if (reply->error() == QnetworkReply::NoError) { // Se nao houve erro, ler os dados da resposta //Ex1: Criando um QImage da resposta QImageReader imageReader(reply); QImage pic = imageReader.read(); }} 22 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]
  • 23. Canais de comunicação• @nokiadev_brasil• rodrigo.belem@openbossa.org 23 INdT 2012 | Filename.pptx v. 0.1 YYYY-MM-DD Author Document ID [Edit via Insert > Header & Footer]