Results 1 to 10 of 10

Thread: Using QTcpSocket to download image from the web

  1. #1
    Join Date
    Jul 2009
    Posts
    21
    Thanks
    1

    Default Using QTcpSocket to download image from the web

    Hello everybody.

    I know there were many topics with similar subjects, but I can't seem to find an answer for my problems so... here we are.

    I want to create application, that would be able to download images from the internet. I know I could use QNetworkManager, but I would like to display image as soon as some part of it gets downloaded (like most browsers do), and QNetworkManager seems to display image after download is complete, so I want to try QTcpSocket. As a test, I am trying to download this image:

    http://www.google.pl/images/srpr/nav_logo73.png

    Here is some code:

    Qt Code:
    1. QTcpSocket socket;
    2. connect(&socket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error(QAbstractSocket::SocketError)));
    3. socket.connectToHost("www.google.pl",80,QIODevice::ReadWrite);
    4. socket.waitForConnected();
    5.  
    6. socket.write("GET /images/srpr/nav_logo73.png");
    7.  
    8. socket.waitForReadyRead();
    9. ba=socket.readAll();
    10. MB.setText(QString(ba));
    11. MB.exec();
    12.  
    13. .
    14. void MainWindow::error(QAbstractSocket::SocketError socketError)
    15. {
    16. MB.setText("Error! "+QString::number(socketError));
    17. MB.exec();
    18. }
    To copy to clipboard, switch view to plain text mode 

    Of course the above is meant to display any data that gets to the byteArray, but even this doesn't work, I got "SocketTimeoutError". What am I doing wrong?

    Thanks in advance.

  2. #2
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Using QTcpSocket to download image from the web

    Your example is assuming a blocking socket rather than reading data whenever it is available.

    Also, QNetworkAccessManager also emits the readyRead() signal whenever new data arrives.

  3. #3
    Join Date
    Jul 2009
    Posts
    21
    Thanks
    1

    Default Re: Using QTcpSocket to download image from the web

    @squidge:

    Thanks for the reply, I have modified my application, and now I use signals instead of blocking code:

    Qt Code:
    1. socket.connectToHost("google.pl",80);
    2. connect(&socket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error(QAbstractSocket::SocketError)));
    3. connect(&socket,SIGNAL(readyRead()),this,SLOT(read()));
    4. connect(&socket,SIGNAL(connected()),this,SLOT(connectX()));
    5.  
    6. void MainWindow::connectX()
    7. {
    8. socket.setSocketOption(QAbstractSocket::KeepAliveOption,1);
    9. QUrl url("http://www.google.pl/images/srpr/nav_logo73.png");
    10.  
    11. ui->statusBar->showMessage("CONNECTED");
    12. socket.write("GET "+ url.toEncoded(QUrl::RemoveScheme | QUrl::RemoveAuthority) +"\r\n");
    13. }
    14.  
    15. void MainWindow::read()
    16. {
    17. ba+=socket.readAll();
    18. }
    19.  
    20. void MainWindow::error(QAbstractSocket::SocketError socketError)
    21. {
    22. ui->statusBar->showMessage("Error! "+QString::number(socketError));
    23. }
    To copy to clipboard, switch view to plain text mode 


    however weird thing is that with some links it works OK (like the google link mentioned in the first post), but with others I get "Bad request", also I can do:

    Qt Code:
    1. socket.write("GET /images/srpr/nav_logo73.png\r\n");
    To copy to clipboard, switch view to plain text mode 

    but not HEAD:

    Qt Code:
    1. socket.write("HEAD /images/srpr/nav_logo73.png\r\n");
    To copy to clipboard, switch view to plain text mode 

    which gives me "Bad request".

    I am not a networking expert (obviously ;] ) but I think the problem is that while browsers and QNetworkAccesManager sends GET, HEAD and other HTTP requests that they are somehow identified (by wireshark for example) as HTTP, and my requests are identified as TCP (wireshark informs me that my requests are "TCP segment of a reassembled PDU", when I look inside I can see my request), please correct me if I am wrong.

    How can I fix that?

    Also, QNetworkAccessManager also emits the readyRead() signal whenever new data arrives.
    But how can I read that data? I don't see any read function for QNetworkAccessManager that could be used here to read partial data, unless cache() can be used in that manner?

    Thanks in advance.

    EDIT:

    OK now I see that I can use something like:

    Qt Code:
    1. QNetworkAccessManager *manager = new QNetworkAccessManager(this);
    2. QNetworkReply *reply;
    3.  
    4. reply=manager->get(QNetworkRequest(QUrl("http://www.google.pl/images/srpr/nav_logo73.png")));
    5. connect(reply,SIGNAL(readyRead()),this,SLOT(read2()));
    6.  
    7. void MainWindow::read2()
    8. {
    9. ba+=reply->readAll();
    10. QPixmap temp;
    11. temp.loadFromData(ba);
    12. ui->display->setPixmap(temp);
    13. }
    To copy to clipboard, switch view to plain text mode 

    and it works however is something like the above safe to use?
    Last edited by Huk; 30th June 2011 at 11:03.

  4. #4
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Using QTcpSocket to download image from the web

    I don't see any problems with using code like that. The only thing I can think of is if the 'get' function finishes before your connect is executed, but that is unlikely (impossible?) to happen as the event driven architecture will not run until your function completes anyway.

  5. #5
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Using QTcpSocket to download image from the web

    Quote Originally Posted by Huk View Post
    however weird thing is that with some links it works OK (like the google link mentioned in the first post), but with others I get "Bad request", also I can do:

    Qt Code:
    1. socket.write("GET /images/srpr/nav_logo73.png\r\n");
    To copy to clipboard, switch view to plain text mode 

    but not HEAD:

    Qt Code:
    1. socket.write("HEAD /images/srpr/nav_logo73.png\r\n");
    To copy to clipboard, switch view to plain text mode 

    which gives me "Bad request".

    I am not a networking expert (obviously ;] ) but I think the problem is that while browsers and QNetworkAccesManager sends GET, HEAD and other HTTP requests that they are somehow identified (by wireshark for example) as HTTP, and my requests are identified as TCP (wireshark informs me that my requests are "TCP segment of a reassembled PDU", when I look inside I can see my request), please correct me if I am wrong.

    How can I fix that?
    A correct GET or HEAD request looks like:
    Qt Code:
    1. GET /images/srpr/nav_logo73.png HTTP/1.0\r\n
    2. HEAD /images/srpr/nav_logo73.png HTTP/1.1\r\n
    To copy to clipboard, switch view to plain text mode 
    (See http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html)
    Some servers will accept malformed requests, some won't. If you are going to reinvent the wheel, try to make it round

  6. #6
    Join Date
    Jul 2009
    Posts
    21
    Thanks
    1

    Default Re: Using QTcpSocket to download image from the web

    @ChrisW67:

    I realize that ;] however if I add "HTTP/1.1 or HTTP/1.0 or HTTP/1." suffix I get no data at all, not even an error, so there still must be something wrong, and I have no idea what... however I am still opened to suggestions, although I will use QNetworkAccessManager, I would still like to know why QTcpSocket GET and HEAD doesn't work.

    Thanks for help so far.

  7. #7
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Using QTcpSocket to download image from the web

    Maybe you are not terminating the lines properly. The best way to find out is to use something like Wireshark or similar which will show you the exact data being sent and received. You can then compare this to an application which gets the proper response.

  8. #8
    Join Date
    Jul 2009
    Posts
    21
    Thanks
    1

    Default Re: Using QTcpSocket to download image from the web

    @squidge:

    Yes, that was the problem ;]

    Instead of:

    Qt Code:
    1. GET /images/srpr/nav_logo73.png HTTP/1.0\r\n
    To copy to clipboard, switch view to plain text mode 

    we have to write:

    Qt Code:
    1. GET /images/srpr/nav_logo73.png HTTP/1.0\r\n\r\n
    To copy to clipboard, switch view to plain text mode 

    now it works, and Wireshark finally see this as HTTP request

    Also some servers seem to require you to specify the host like this:

    Qt Code:
    1. GET /images/srpr/nav_logo73.png HTTP/1.1\r\nHost: www.google.pl\r\n\r\n
    To copy to clipboard, switch view to plain text mode 

    otherwise you will get "Bad request".

    Thanks for the help everyone.

    Problem seems solved

  9. #9
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Using QTcpSocket to download image from the web

    Yes, sometimes the host is required because more than one website is hosted on one IP address.

    Best thing to do is to always provide it.

    But now you know how it works, you'll be using QNetworkManager anyway, right?

    (and don't forget some hosts will return status codes such as 'redirection', you must handle these as well)

  10. #10
    Join Date
    Jul 2009
    Posts
    21
    Thanks
    1

    Default Re: Using QTcpSocket to download image from the web

    Yes, sometimes the host is required because more than one website is hosted on one IP address.

    Best thing to do is to always provide it.

    (and don't forget some hosts will return status codes such as 'redirection', you must handle these as well)
    I see, thanks for the information.

    But now you know how it works, you'll be using QNetworkManager anyway, right?
    For the current application: yes, but if I ever need to create something more advanced, QTcpSocket will definitely be used there

Similar Threads

  1. From where should I download QML
    By prajnaranjan.das in forum Qt Programming
    Replies: 1
    Last Post: 10th February 2011, 19:54
  2. Reimplement QTcpSocket to limit download speed ???
    By THRESHE in forum Qt Programming
    Replies: 3
    Last Post: 29th November 2010, 14:30
  3. download and store/show image
    By peter_hr892h in forum Qt Programming
    Replies: 3
    Last Post: 25th June 2009, 05:16
  4. QTCPSocket - Download Speed
    By tntcoda in forum Qt Programming
    Replies: 2
    Last Post: 24th May 2009, 13:47
  5. Download Manager Like IDM(Internet Download Manager)
    By sathiskumarmsk in forum Qt Programming
    Replies: 1
    Last Post: 27th July 2008, 15:52

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.