I am trying to connect GPRS GSM A6 to arduino. Everything works fine, but there is a slight problem.
And its that AT+CIPSTART only accepts IP or domain name.
For example this,
AT+CIPSTART="TCP", "xxx.xx.x.xxx", 80
works fine, Or this,
AT+CIPSTART="TCP", "www.google.com", 80
also works fine, but what I am looking for is something like this.
AT+CIPSTART="TCP", "xxx.xx.x.xxx/trackerCode/", 80
That is I want to specify directory along with the ip. But it does not allow me to do this and returns a +CME Error.
Is there a way to do this?
The only way would be direct support in your GPRS module firmware. So start with available AT commands with something like HTTP in it.
If there is none, you have to send HTTP request over TCP connection openned by examples 1 or 2. How the HTTP protocol looks like is defined in RFC 2612. Request name, path and http version on the first line are mandatory, few more headers might be needed (for the server with virtual domains it'll be Host header)
And line endings must be "\r\n"
Related
I'm writing my own client and server, they are implement my own application level protocol. For transport layer TCP is used. For internet layer IPv4 is used. Nor TCP header, nor IPv4 header not contain any information about URL path. TCP header contains port, IPv4 contains IP address. Who should contain path?
So, consider this URL - 127.0.0.1:4444/location-path. 127.0.0.1 is supposed to be part of IPv4. 4444 is supposed to be part of TCP. For example, in Golang, using standard net.Dial() and net.Listen(), I can only use 127.0.0.1:4444. Using of 127.0.0.1:4444/location-path will throw an error, which is really expected because it provides support only for TCP/IP/domain name resolving, and /location-path is not part of all these three.
So, on client and server side, how I should handle /location-path in a such way that client can send requests to different locations and server can serve different locations?
Every application protocol should implement its own logic to handle /location-path?
According to RFC 1738:
url-path
The rest of the locator consists of data specific to the
scheme, and is known as the "url-path". It supplies the
details of how the specified resource can be accessed. Note
that the "/" between the host (or port) and the url-path is
NOT part of the url-path.
The url-path syntax depends on the scheme being used, as does the
manner in which it is interpreted.
So, I can implement my own rules for url-path and how it will be interpreted by client and server? And to transfer it I can just send it as a data?
For example, I can just define rules that my own application level protocol - proto - will place url-path at first four bytes of TCP payload? So, proto://127.0.0.1:4444/path will become 127.0.0.1:4444 with TCP payload [112 97 116 104].
The easiest way to compare this is HTTP.
A http url might look like http://example:1234/bar
A http client understands that URL. The HTTP client will (under the hood) still make a standard TCP connection to get there.
It does this by grabbing the host and port portion, and (temporarily) discard everything else. So only example and 1234 is used in that stage.
After the TCP connection is established, it will use the path part and send it as the first line.
TCP clients don't know about URLs, they know about hosts and ports. What you do with the path portion is up to you.
I'm debugging some DNS issues on a WiFi access point I'm setting up. I am connecting an ESP32 to my network so it can output what it's up to. I want to get my Public IP address as a test and I want to use http://ifconfig.me/ip to go and get it. This is superb when DNS is working, but as per standard HTTPS stuff, I can use the Host: name header in a call to the IP address to test connectivity to determine if it's just a DNS failure I'm seeing. If I set up the following in Postman, everything is super...
When I do the following on the ESP32, which should mimic the above, I get a 404 - which happens when the Host header is not sent or is incorrect.
...
String new_url = "http://34.117.59.81/ip";
String host = "ifconfig.me";
HTTPClient http;
http.begin(new_url.c_str());
http.addHeader("Host", host.c_str());
int httpResponseCode = http.GET();
...
What am I doing wrong? I've tried the addHeader() call either side of the begin()
I've tried collectHeaders() call, but that only keeps the response headers so I can't see what I'm actually sending.
On the positive note, the fact I'm getting a 404 does mean connectivity is fine, and the issue is my DNS as expected, but why can't I (allegedly) send the Host header?
The HTTPClient library adds the Host header for you automatically.
The library is written to silently ignore attempts to add your own Host field (along with Connection, UserAgent and Authorization):
// not allow set of Header handled by code
if(!name.equalsIgnoreCase(F("Connection")) &&
!name.equalsIgnoreCase(F("User-Agent")) &&
!name.equalsIgnoreCase(F("Host")) &&
!(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())){
String headerLine = name;
Unfortunately it doesn't currently offer a method to tell it to use a particular Host with an IP address that's not resolved from it.
You could copy the library into your project and just delete the check that stops it from using your Host field. Or (I hate suggesting this because I usually push people to use the HTTPClient library rather than roll their own) you could do your own simple HTTP implementation using WiFiClient.
It sounds like you understand this already but for others who may read this, HTTP allows one IP address to serve multiple domains (back in the old days it didn't but as we ran low on IP addresses this became critical). The server uses the Host field to decide which domain to direct traffic to. It's likely that the server you're connecting to is accepting the connection but without the Host field being set properly the request isn't making it to the correct server and is failing with a 404.
Now i am getting super confused with how ports actually work ,
This is my understanding of ports. I know that port 80 is for HTTP protocol and port 443 is for HTTPS protocol, so whenever I access http://website.com [(name or ip)], it is converted to http://website.com:80 [(name or ip)], and when I access https://website.com [(name or ip)], it gets converted to https://website.com:443 [(name or ip)].
So, if i am accessing a website on another port, i.e, i have my local setup of either springboot or angular app, and they are HTTP endpoints,
and I access http://localhost:someportNumber (example: http://localhost:5000), how does that get translated to port, as I have explicitly specified port 5000, but HTTP works on port 80.
Can you please help me with my understanding of how ports works.
Till now I was clear on how ports work, but now when I think of it like this today, it challenges my understanding of ports.
I came across this conflict of understanding when I was learning about the services on Google Kubernetes Engine. In there I created a service of type nodeport, which had configs like
port: 443
targetPort: 443
nodePort: 31000
and when I accessed external ip address of one of the nodes https://[external-ip]:31000, it worked.
So I began to challenge my understanding and I can't wrap this around my head that how is it working.
PS:- It is not about the concept of NodePort/ClusterIP/LoadBalancer. But in general about how these ports work with protocol port http or https, with a port of application.
You can specify any port (such as 5000 in your example). The URI simply begins with http to indicate what protocol is used - it does not mandate the use of port 80. The address is then used to contact the host on the specified port (which will be port 80 unless a different port was specified). Upon successful connection, the client then expects the server to speak HTTP.
On the server side, there is just a program that is listening on a port, waiting for incoming connections.
In the old days, one wouldn't call a person at a company directly. Instead one would call the main company switchboard and ask for the person at some extension.
Operator: How can I help you?
You: Extension 123
Operator: Connecting you now
Think of a "port" like an extension at a company. The hostname/IP address is the phone number of the company, the port is the extension at that company.
Going back to the analogy, once you are connected to the phone extension, you have a conversation. Both parties have an expectation of the conversation to be had. For example, if I call the extension corresponding to sales, I can place an order while if I call the extension corresponding to recruitment, I can submit my resume. This relationship between the purpose of the call and the extension is by convention and is not implicit in the extension itself.
When you form a connection over the internet to some machine at port 80, the assumption is that we will be exchanging HTTP traffic. However if I form a connection to some machine at port 5000, then there is nothing to prevent THAT connection from also sending and receiving HTTP traffic. For example, if sales at my company can be contacted on extension 80 and you can place an order there may also be an additional extension (5000) which you can call to place other types of orders that aren't available at the 80 extension.
See also:
http://www.steves-internet-guide.com/tcpip-ports-sockets/
I'm using qnetworkaccessmanager for making HTTP requests. The hostname (FQDN) of the server I connect to, has two IP addresses in DNS and I need to control which one to use. The obvious solution (change the URL's hostname to IP address) does not work, because the server sends back a 302 redirect with the original hostname in the location field. If I follow the redirect, QT seems to randomly choose which IP it connects to.
Is there a way to tell qnetworkaccessmanager to use a given IP address on the TCP connect() level and use the Host header from the URL ? If not, any workaround suggestions are appreciated.
Edit: using QT 4.7.4
This seems to work and is a simple workaround: set the QNetworkRequest's URL to contain the desired IP address to connect to in the host part, but also use setCustomHeader("Host", "<server hostname>") to avoid the redirection. In my tests, QT will always use the IP set in the URL.
You should be able to build a custom QNetworkRequest and specify the QNetworkRequest::LocationHeader to force a specific destination URL in case of a redirect. If you look at QNetworkAccessManager::sendCustomRequest (QNetworkAccessManager::sendCustomRequest doc), and QNetworkRequest::Attribute::RedirectionTarget and QNetworkRequest::KnownHeaders it should give you some hints about it.
(footnote: I'm using the harmattan documentation as the proper Qt documentation is down as of time of answer)
I'm trying to call a HTTP JSON-RPC server for Bitcoin using Go (not on GAE), but I get error of
dial tcp http://user:pass#127.0.0.1:8332: too many colons in address
or
dial ip http://user:pass#127.0.0.1:8332: lookup http://user:pass#127.0.0.1:8332: no such host
I tried various network configurations, but couldn't get anything going. When I just typed the address into the browser, I got a response from the server:
{"result":null,"error":{"code":-32700,"message":"Parse error"},"id":null}
Which looks like a proper response for an empty call.
How do I correctly call that HTTP JSON-RPC server in Go?
Use brackets around the host like this:
[user:pass#127.0.0.1]:8332
Reference:
http://golang.org/src/pkg/net/ipsock.go?s=2247:2304#L68