Qt Network Explained (Portuguese)
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Qt Network Explained (Portuguese)

on

  • 723 views

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 ...

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.

Statistics

Views

Total Views
723
Views on SlideShare
723
Embed Views
0

Actions

Likes
0
Downloads
4
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Qt Network Explained (Portuguese) Presentation 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]