Qt: Use tcp socket to get google map image? - qt

For some reason I need to use a blocking call to perform image accessing from google's server.
However, QNetworkAccessManager seems to be async, though there are many work arounds, like calling a eventLoop.exec(); many people online suggested me not to do so.
So I am trying to use TCP socekt.
I want to access the image here:
http://mt1.google.com/vt/lyrs=y&x=0&y=0&z=0
And here is my code:
socket = new QTcpSocket(this);
socket->connectToHost("mt1.google.com", 80, QIODevice::ReadWrite);
if(socket->waitForConnected(5000))
{
qDebug() << "Connected!";
// send
socket->write("/vt/lyrs=y&x=0&y=0&z=0");
socket->waitForBytesWritten(1000);
socket->waitForReadyRead(3000);
qDebug() << "Reading: " << socket->bytesAvailable();
// get the data
qDebug() << socket->readAll();
// close the connection
socket->close();
}
else
{
qDebug() << "Not connected!";
}
But it seems to working at all? What should I write through the tcp socket to get the image?

TCP provides only the transport mechanism. Since you are trying to communicate with a web server, you should compose HTTP messages.
Replace the line
socket->write("/vt/lyrs=y&x=0&y=0&z=0");
with
socket->write("GET /vt/lyrs=y&x=0&y=0&z=0 HTTP/1.1\r\nHost: mt1.google.com\r\nUser-Agent: TestAgent\r\n\r\n");
And you should get the following response :
HTTP/1.1 200 OK
Date: Sun, 14 Jun 2015 14:24:40 GMT
Expires: Sun, 14 Jun 2015 14:24:40 GMT
Cache-Control: private, max-age=3600
Access-Control-Allow-Origin: *
Content-Type: image/jpeg
X-Content-Type-Options: nosniff
Server: paintfe
Content-Length: 10790
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Alternate-Protocol: 80:quic,p=0
IMAGEDATA
Parse the response and extract the IMAGEDATA part.
EDIT : TCP delivers the response divided into chunks. With this approach, you will not be able to receive the whole response since you are trying to receive it in one go.
You should examine the Content-Length header and wait until receiveing the specified amount of bytes.

Related

Why is my request returning incomplete multipart?

I am using my Arduino to do a multipart/form-data request. I am generating the request completely by myself as follows:
client.println(HTTP_METHOD + " " + PATH_NAME + " HTTP/1.1");
client.println("Host: " + String(HOST_NAME));
client.print(F("Content-Type: multipart/form-data; "));
client.print(F("boundary=\"AaB03x\"\r\n"));
client.print(F("Content-Length: "));
client.print(strlen("{json data here}")
+ strlen("{json data here}"));
client.print("\r\nConnection: close\r\n");
// First part
// Boundary
client.print(F("\r\n--AaB03x\r\n"));
// Headers
client.print(F("Content-Disposition: form-data; name=\"header\"\r\n"));
client.print(F("Content-Type: application/ld+json\r\n"));
client.print(F("Content-Length: "));
client.print(strlen("{json data here}"));
client.print(F("\r\n\r\n"));
// Content
client.print(F("{json data here}"));
// Second part
// Boundary
client.print(F("\r\n--AaB03x\r\n"));
// Headers
client.print(F("Content-Disposition: form-data; name=\"payload\"\r\n"));
client.print(F("Content-Type: application/ld+json\r\n"));//
client.print(F("Content-Length: "));
client.print(strlen("{json data here}"));
client.print(F("\r\n\r\n"));
// Content
client.print(F("{json data here}"));
// End of boundary
client.print(F("\r\n--AaB03x--\r\n\r\n"));
However the server returns "Incomplete multipart" which I don't understand since the multipart seems completely fine. I thought it was maybe due to incorrect newlines but I haven't been able to figure out a solution.
The output can be seen below and includes the request sent as well as the response from the server.
GET /router HTTP/1.1
Host: 192.168.178.147
Content-Type: multipart/form-data; boundary="AaB03x"
Content-Length: 4363
Connection: close
--AaB03x
Content-Disposition: form-data; name="header"
Content-Type: application/ld+json
Content-Length: 4143
{
some data here
}
--AaB03x
Content-Disposition: form-data; name="payload"
Content-Type: application/ld+json
Content-Length: 220
{
some data here
}
--AaB03x--
connected to 192.168.178.147
HTTP/1.1 500 Server Error
Connection: close
Cache-Control: must-revalidate,no-cache,no-store
Content-Type: text/html;charset=iso-8859-1
Content-Length: 597
Server: Jetty(9.4.41.v20210516)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 500 Server Error</title>
</head>
<body><h2>HTTP ERROR 500 Server Error</h2>
<table>
<tr><th>URI:</th><td>/router</td></tr>
<tr><th>STATUS:</th><td>500</td></tr>
<tr><th>MESSAGE:</th><td>Server Error</td></tr>
<tr><th>SERVLET:</th><td>org.apache.camel.component.jetty.CamelContinuationServlet-38cb1606</td></tr>
<tr><th>CAUSED BY:</th><td>java.io.IOException: Incomplete Multipart</td></tr>
</table>
<hr>Powered by Jetty:// 9.4.41.v20210516<hr/>
</body>
</html>
Your Content-Length calculations are suspect.
Drop the Content-Length headers for each sub-section in the multipart and try again, those are not needed for multipart, and your calculations are just wrong anyway.
You can see captures of various multipart requests from various libraries and browsers in the Jetty tests.
https://github.com/eclipse/jetty.project/tree/jetty-9.4.41.v20210516/jetty-http/src/test/resources/multipart
(Look at the ones ending in *.raw, which you can generally open in a text editor)
Tip: don't do this yourself, multipart mime is full of edge cases, traps, and ancient tricks. Go grab apache httpcomponents httpmime jar and just use it to generate your raw mime multipart section properly.
Artifacts - https://search.maven.org/artifact/org.apache.httpcomponents/httpmime
Javadoc - https://javadoc.io/doc/org.apache.httpcomponents/httpmime/latest/index.html

IP Camera viewer in android

I am doing a project in which ,I have to stream the ip camera's live in my app.
For demo I am using DLink camera(DCS 942L) .Please help me how to stream this ip camera's live in my app.
i succeed access to your camera, i make a http query using dlink:dlink as user:password :
1) before all, i encode dlink:dlink using Base64 encoder it give me ZGxpbms6ZGxpbms=
2) i send the query in c/c++ as follow:
sockaddr_in sin;
char *ip="203.125.227.73";
int port=80;
sin.sin_addr.s_addr=inet_addr(ip); // IP of server
sin.sin_family= AF_INET;
sin.sin_port=htons(port);
int sock=socket(AF_INET,SOCK_STREAM,0);
connect(sock, (sockaddr *)&sin, sizeof(sin));
char s[1024];
strcpy(s,"GET /video/mjpg.cgi HTTP/1.1\r\n"
"Authorization: Basic ZGxpbms6ZGxpbms=\r\n\r\n");
send(sock,s,strlen(s),0);
the server send me back this:
HTTP/1.0 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Content-Type: multipart/x-mixed-replace;boundary=myboundary
--myboundary
Content-Type: image/jpeg
Content-Length: 32616
X-Status: 00000000
X-Tag: 830892
X-Flags: 0
X-Framerate: 20.92
X-Resolution: 640*360
X-Audio: 0
X-Timestamp: 1386117639854
\r\n\r\n followed_by_jpeg_data_stream_that_you_have_to_decode_in_bmp_and_display_it
in my case i use libjpeg in android and turbo-jpeg in windows to decode the stream.
dont forget to change the username and password, you can encode quickly the new user:pass in this web website:
http://www.motobit.com/util/base64-decoder-encoder.asp

restlet get not sending close response

I have the following get in my restlet app:
#Get
public String represent(Variant variant) throws ResourceException
{
String text = "returntext";
text+="\r\n";
return text;
}
When checking the response from invoking this service, I get the following:
CFG - HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Type: text/plain;charset=UTF-8
Date: Mon, 29 Jul 2013 19:59:37 GMT
Server: Restlet-Framework/2.0.9
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Content-Length: 118
Connection: keep-alive
Shouldn't the Connection be: closed as opposed to keep-alive?
I think is causing the connection to get tied up because I can only invoke the service once.
#Ab is correct. http 1.1 has a keep alive. This was the problem.

HttpClient request to local IIS 8.0 does not produce expected headers in the response

I'm making the following request to a local website running in IIS
var httpRequestMessage = new HttpRequestMessage();
httpRequestMessage.RequestUri = new Uri("http://localhost:8081/");
httpRequestMessage.Method = HttpMethod.Get;
var response = new HttpClient().SendAsync(httpRequestMessage).Result;
This produces the following response headers:
HTTP/1.1 200 OK
Accept-Ranges: bytes
Date: Mon, 03 Jun 2013 22:34:25 GMT
ETag: "50c7472eb342ce1:0"
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
An identical request made via Fiddler produces the following response headers (I've highlighted the differences):
HTTP/1.1 200 OK
Content-Type: text/html
Last-Modified: Fri, 26 Apr 2013 19:20:58 GMT
Accept-Ranges: bytes
ETag: "50c7472eb342ce1:0"
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
Date: Mon, 03 Jun 2013 22:29:34 GMT
Content-Length: 10
Why is there a difference in response headers?
Am I using HttpClient correctly (aside from the fact I am calling Send synchronously)?
TL;DR;
To access all response headers you need to read both HttpResponseMessage.Headers and HttpResponseMessage.Content.Headers properties.
Long(er) answer:
This, basically:
var response = new HttpClient().GetAsync("http://uri/").Result;
var allHeaders = response.Headers.Union(response.Content.Headers);
foreach (var header in allHeaders)
{
// do stuff
}
I see two issues with this:
The Headers property is not appropriately named: it should really be SomeHeaders or AllHeadersExceptContentHeaders. (I mean, really, when you see a property named Headers, do you expect it to return all headers or some headers? I am pretty sure they are in violation of their own framework design guidelines on this one.)
The MSDN page does not mention at any point the fact this is a subset of all headers and developers should also inspect Content.Headers.

Asp.Net Sending PDF to browser

I've been trying to get this aspx page to serve up a pdf. It works correctly in Firefox, but IE gives
Internet Explorer cannot download getform.aspx from SERVER_NAME
Internet Explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found.
This is the general functionality of my code. It's spread across multiple functions (this is why we're not using WriteFile - sometimes we generate the pdf on the fly), but this is generally it:
FileStream fs = File.Open(Path.Combine(PdfBasePath, "form.pdf"), FileMode.Open, FileAccess.Read);
Stream output = Response.OutputStream;
byte[] buffer = new byte[BUFFER_SIZE];
int read_count = fs.Read(buffer, 0, BUFFER_SIZE);
while (read_count > 0)
{
output.Write(buffer, 0, read_count);
read_count = fs.Read(buffer, 0, BUFFER_SIZE);
}
fs.Close();
Response.Clear();
Response.ContentType = System.Net.Mime.MediaTypeNames.Application.Pdf;
Response.AddHeader("Content-Disposition", "attachment; filename=form.pdf");
Response.Output.Flush();
Response.End();
Looking at Fiddler, the page is being fetched using this:
GET /getform.aspx?Failure=Y&r=someencryptedstring HTTP/1.1
It is being returned to the browser thus:
HTTP/1.1 200 OK
Date: Thu, 09 Apr 2009 22:08:33 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Pragma: no-cache
Content-Disposition: attachment; filename=form.pdf
Cache-Control: no-cache, no-store
Pragma: no-cache
Expires: -1
Content-Type: application/pdf
Content-Length: 628548
This is really bugging me. I'm not using SSL, otherwise this KB article would seem to apply. Anyone have any ideas?
Is the Content-Length being returned in the header actually correct for the file you're sending? I'm just comparing this to some production code we use here and it looks like we explicitly set the Content-Length header. If I recall correctly, some browsers have a problem if the header and the actual file size don't match.
Edit
The question author found that changing the Content-Disposition header to application/download instead of application/pdf seems to work around the problem.

Resources