| March 30, 2011 12:00 AM PDT | |
Introduction
With so many connected devices in the market today, enabling connectivity to online resources is becoming a vital part of application development. Since MeeGo* supports a breadth of platforms, making the effort to write robust, connected applications that run within the MeeGo framework can pay off in multiple segments with few platform specific modifications. Below I will use two examples to describe how the MeeGo application framework and Qt* provide the appropriate level of abstraction to enable rapid and reliable development while still giving the flexibility to accommodate those corner cases that can affect network communication.The first example is a very simple web browser using the WebKit* based QWebView class that demonstrates the power and flexibility of using Qt when creating cross-platform, Internet enabled applications. The second example demonstrates using a lower-level class, QNetworkAccessManager that provides flexible access to network resources independent of WebKit. In these examples we'll focus on the most common protocols such as HTTP over TCP/IP, but many of the classes used support other protocols as well.
Throughout this discussion it is assumed that you have a Qt SDK installed and configured for your target devices. This may be part of your MeeGo SDK installation but the examples shown here do not require that you are building for a MeeGo target. You should have a basic understanding of using Qt Creator* and Qt Designer* as well as the Qt framework including concepts like signals and slots. You need not have an extensive knowledge of networking or the networking classes in Qt. You only need to be able to set up a test system on an active network, preferably with Internet access. We'll go into a few examples of Potential Issues that can be encountered when connecting to networked resources and how to address them in the examples.
Overview of MeeGo Networking
On MeeGo, the key components related to network and Internet communications are the oFono* modem plugin/driver and the Linux* network interface for the Linux* TCP/IP stack. The MeeGo WLAN architecture is based on the Linux wireless (IEEE-802.11) specification. The details of these core components are abstracted by the Qt framework so a deep understanding of these drivers and specifications is not necessary in order to rapidly develop networked applications.Example: QWebView
You can create a quick application in Qt to access and display standard HTTP resources without any prior knowledge of the network environment in which a device is operating. This example will walk through creating a simple WebKit based browser window as shown in Figure 1.
Figure 1.
We'll start by creating a new Qt C++ GUI application in Qt Creator/Designer named QWebView accepting all default names for files. The project should now contain:
- QWebView.pro - the Qt project file
- mainwindow.ui - the definition of the main window GUI
- mainwindow.h - the header file for the main window
- main.cpp - the source file for the application
- mainwindow.cpp - the source file for the main window
- QLineEdit named urlEdit
- QPushButton named refreshButton
- QWebView named webView
- QTextEdit named debugTextView
:: error: collect2: ld returned 1 exit status
Your project file should contain the following line:
QT += core gui network webkit
You will also need to include the QtWebKit module in the header file for your main window class, mainwindow.h.
#include <QtWebKit>To show just how simple it is to create a feature rich, networked application, we will simply have the refreshButton load a website address. To illustrate a few other options of the QWebView class, we will also add some basic debug information to the debugTextView box. The code below should be added to the source file for the window class, mainwindow.cpp.
void MainWindow::on_refreshButton_clicked()
{
QString targetURL = ui->urlEdit->text();
ui->debugTextView->append("URL Entered: " + targetURL);
ui->webView->load(QUrl(targetURL));
}
void MainWindow::on_webView_loadStarted()
{
ui->debugTextView->append("Load Started");
}
void MainWindow::on_webView_loadFinished(bool )
{
ui->debugTextView->append("Load Finished");
}
We also need to add the corresponding function declarations to the mainwindow.h header file.private slots:
void on_webView_loadFinished(bool );
void on_webView_loadStarted();
void on_refreshButton_clicked();
Tip: The function declarations and definition templates are added to your code automatically if you use the "Go to slot..." feature in Qt Designer to. This is done by right-clicking an object in Qt Designer, selecting "Go to slot…" and choosing from the available slots for that object.Notice that much of the code is for the debug information. Only a few lines are actually required to create our functional web browser.
After building and running the project, you should see that a valid URL entered in the urlEdit box will display the corresponding page in the webView window once the refreshButton is clicked. You should also see some basic information in the debugTextView box. In some environments the application may not function correctly. We'll address Potential Issues below. You can jump there now if your example is not working.
What we've seen so far is that the QWebView class gives us a functional web browser with very little effort. If you explore the QWebView class, you'll see that without adding additional controls, you even have some navigation capabilities such as "Go Back" and "Refresh" that are presented when you right-click within the QWebView object as the application is running. There are even more properties and functions you can access for creating a richer web browsing experience which are described in the QWebView documentation. Two examples are the loadStarted and loadFinished slots. These can give the user some indication that network operations are occurring and that they should not yet expect to see a result. You could add many enhancements to this example to make it more user friendly and robust, but that is outside the scope of this discussion. The key here is that many of the abstract objects available in Qt can provide rich network functions without requiring direct access to the underlying network infrastructure. But what if you don't need such a feature rich object for the purposes of your project?
Example: QNetworkAccessManager
Perhaps you just want to access an online resource and grab some basic information to use in your application. An example could be accessing RSS (Real Simple Syndication) data to dynamically drive the content displayed in your application. For this purpose, you may not want the overhead of a complete web browser but you still need not worry about the details of the underlying network infrastructure - at least not always.
QNetworkAccessManager is a convenient class for interacting with network resources but at a lower level than that of something like the QWebView class. To demonstrate this, we create a new example that connects to a website URL and just reads and displays the network response of an HTTP get operation as shown in Figure 2.
Figure 2.
We'll start this example by again creating a simple Qt C++ GUI project named QNetworkAccessManager accepting all default names for files. The project should now contain:
- QNetworkAccessManager.pro - the Qt project file
- mainwindow.ui - the definition of the main window GUI
- mainwindow.h - the header file for the main window
- main.cpp - the source file for the application
- mainwindow.cpp - the source file for the main window
- QLineEdit named urlEdit
- QPushButton named fetchButton
- QTextEdit named returnText
private:
Ui::MainWindow *ui;
QNetworkAccessManager *netmanager;
void fetchURL(QUrl);
We must remember to also include the QNetwork module before declaring our QNetworkAccessManager object in mainwindow.h.#include <QtNetwork>You also must add network to the QT line of your project file:
QT += core gui networkfetchURL is going to take a URL passed to it and perform an HTTP get operation. The implementation in mainwindow.cpp looks like this:
void MainWindow::fetchURL(QUrl targetURL)
{
netmanager->get(QNetworkRequest(targetURL));
}
I chose to create a separate function for this simple operation so that I can add more to it later to make the application more robust.When the main window is created, we will initialize the QNetworkAccessManager object and connect its finished signal to a slot in our window class that will process the reply. Many functions in the QNetworkAccessManager class are asynchronous so Qt signals and slots become very convenient. We first define a fetchFinished slot in the main window's header, mainwindow.h.
private slots:
void fetchFinished(QNetworkReply*);
Then we add this code to the window's constructor in mainwindow.cpp.MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// The following coded added for our example
netmanager = new QNetworkAccessManager(this);
connect(netmanager, SIGNAL(finished(QNetworkReply*)), this,
SLOT(fetchFinished(QNetworkReply*)));
}
The fetchFinished slot is implemented like this in mainwindow.cpp.void MainWindow::fetchFinished(QNetworkReply* reply)
{
ui->returnText->append("Fetch Finished!");
QString *replyText = new QString(reply->readAll());
ui->returnText->append(*replyText);
}
For simplicity, I'm just displaying a message indicating that the slot was called and then copying the byte array in the reply directly to our output window. In a real application, the reply would likely be parsed and acted on. For example, you might be writing a news aggregator and want to grab headlines from a particular news source. You can perform a get on a URL such as http://velonews.competitor.com/feed feed and parse out the <title> tags in the resulting XML to create a list of professional cycling headlines.The last thing to do for this example to be functional is to act on the fetchButton clicked signal. We'll do this by adding the following code to the mainwindow.cpp source file.
void MainWindow::on_fetchButton_clicked()
{
QUrl targetURL = QUrl(ui->urlEdit->text());
fetchURL(targetURL);
}
Don't forget to add the corresponding definition to mainwindow.h if you didn't use the "Go to slot…" feature of Qt Designer.void on_fetchButton_clicked();Now the example should compile and run. If a valid URL is entered, you should see the contents of the reply. Note that the default QTextEdit object may display HTML code as it would appear in a browser rather than in plain text. Just as you may have seen in the QWebView example, things may not work exactly as expected in all network environments due to several Potential Issues addressed below.
This example shows how to access lower level information from network resources to give finer control in your application. As you explore classes such as QNetworkAccessManager, QNetworkReply and others, you'll see that this is just the beginning of what these classes have to offer. You can choose to use as few or as many of these features to suit your application's needs.
Potential Issues
Am I Online?The most common issue that a network application will encounter is a lack of connectivity. Unfortunately, the only sure way to determine if network connectivity is sufficient to reach a specific resource is to try to access that resource. This trial and error method can take a significant amount of time and frustrate users. Qt offers several classes that give control over network settings and insight into network connectivity. I've spent quite a bit of time exploring these classes on various platforms and in various networks and share some of that experience here.
- QNetworkInterface, among many other things, provides a simple way to enumerate the network interfaces reported by the OS and their network settings such as IP addresses. You can also test flags associated with each interface to determine its state. It is important to keep in mind that just because an interface may be up, it may not be able to access a network resource across the globe or even on the same local network. On the other hand, if no interfaces with valid IP addresses are returned by this class, you can be fairly certain that no network resources will be reachable.
- QNetworkConfigurationManager and QNetworkConfiguration classes provide detailed information about a specific network configuration. One of the more useful properties is the BearerTypeName which may be Ethernet, WLAN, WiMAX, CDMA 2000, etc. Of course the OS must correctly report the type on any give platform.
- QNetworkAccessManager is the basis of the second example here but there are options not shown in the example for checking connectivity. In particular, the networkAccessible() function should return the general state of connectivity for the QNetworkAccessManager object.
Unfortunately, in my testing I was not able to get a return value other than QNetworkAccessManager::UnknownAccessibility.
Redirection
Many Internet URLs redirect to another address meaning that you may need to connect to multiple locations. This is not necessarily an issue for something like the QWebView class that can handle redirection automatically but for simple get operations in a QNetworkAccessManager object, you will need to detect and handle redirections manually.
If in the QNetworkAccessManager example you are seeing a "301 Moved" response, you can add a redirection handler to automatically send the same get request to the new URL. For example, in the fetchFinished slot, you can add this simple check.
void MainWindow::fetchFinished(QNetworkReply* reply)
{
ui->returnText->append("Fetch Finished!");
// Redirection handler
QUrl redirectURL = reply->attribute(
QNetworkRequest::RedirectionTargetAttribute).toUrl();
if(redirectURL.isValid())
fetchURL(redirectURL);
QString *replyText = new QString(reply->readAll());
ui->returnText->append(*replyText);
}
The QNetworkReply object, reply has a RedirectionTargetAttribute from which we can obtain the redirection URL. If it exists, we can call the get operation in our fetchURL function again with this new address.Navigating Proxies
Proxy settings need to be considered in any network application, especially when the application may be used in a corporate environment. Qt offers some very simple methods to accommodate proxy settings. The simplest is to have the application use whatever proxy the system is configured to use assuming there exists a system-wide network configuration manager that the user has configured. In the QNetworkAccessManager example, you can add a single line to the fetchURL function that will cause the get operation to use the system proxy configuration. This line should be added beforevoid MainWindow::fetchURL(QUrl targetURL)
{
// Addition to set system proxy
QNetworkProxyFactory::setUseSystemConfiguration(true);
netmanager->get(QNetworkRequest(targetURL));
}
The same goes for the QWebView example. You can add the same call to the on_refreshButton_clicked() function.void MainWindow::on_refreshButton_clicked()
{
QString targetURL = ui->urlEdit->text();
ui->debugTextView->append("URL Entered: " + targetURL);
// Addition to set system proxy
QNetworkProxyFactory::setUseSystemConfiguration(true);
ui->webView->load(QUrl(targetURL));
}
There are also options that allow finer control over proxy choice all the way down to specifying exact proxy settings for a given connection. It is far more convenient for a user to configure proxy settings at the system level rather than the application level however there may be cases when the user has configured multiple proxies and requires some level of control over which is used at the application level. The systemProxyforQuery function in the QNetworkProxyFactory class can return a list of proxies suitable for a given URL. With this function you can query the proxies for a given URL and display results as a user option.Security
The use of Secure Sockets Layer (SSL) in network communication is becoming more prevalent every day as people are becoming more aware of the need to protect information. Network resources that require SSL add another layer of complexity for network applications. Qt does a good job of hiding many of these complexities in classes like QWebView. In the QWebView example, you may have noticed that some addresses or links just didn't open. This is often caused when no SSL support has been linked in the application and can be confirmed by debug messages displayed in the application output window of Qt Creator during runtime.
On Windows*, the Qt SDK does not have SSL support by default. You must install and configure something like OpenSSL* to get this support. Running the QWebView example on Windows without SSL support can show the issues this will cause. If you try to load something like http://gmail.com/, you may see that nothing is displayed even after the load has finished. You should also notice errors in the Qt Creator application output window.
This is a case where Google* now enforces the use of SSL even if a non SSL address, such as http://gmail.com/, is used. The QWebView object automatically handles the URL redirection to https://gmail.com/ but there is no SSL support and so the load fails. If you are using the MeeGo SDK and building for a recent MeeGo target image, SSL support is included automatically and connections over SSL should succeed.QSslSocket: cannot call unresolved function SSLv3_client_method QSslSocket: cannot call unresolved function SSL_CTX_new QSslSocket: cannot call unresolved function SSL_library_init QSslSocket: cannot call unresolved function ERR_get_error QSslSocket: cannot call unresolved function ERR_error_string
For more information on SSL support in Qt, see the Qt FAQ at http://developer.qt.nokia.com/faq/answer/how_can_i_add_ssl_support_to_my_qt_application.
Summary
Networking is a large and often complicated topic. The information and examples here show that a feature-rich application can be developed in Qt for MeeGo and many other platforms with very little effort. There are quite a few potential pitfalls to avoid, but the Qt framework offers many options to handle those cases as well. For further details on the classes discussed here, follow the Qt documentation links called out in the discussion.About the Author
Tom Propst is a Software Engineer at Intel focusing on mobile application development and optimization. Tom is defined outside of the office by his love for cycling.
For more complete information about compiler optimizations, see our Optimization Notice.
Comments (0) 
Trackbacks (0)
Leave a comment 
To obtain technical support, please go to Software Support.
