This had baffled me for some time. There are many examples of how to do this in previous versions of the ID; however none appeared to work with v1.0 - so I thought I'd share my workaround.
I wanted to record the remote IP address of clients using my Arduino as a web server.
To make it work, I did the following:
I added the following lines to the end of the EthernetClient.cpp file:
Adding to some server code I already have below, I just get 0.0.0.0 printed to the serial monitor. Bottom is where your code is pasted in the .ccp and .h files. Such is the world of copy/paste. This is with the 1.0 IDE.
//zoomkat 12-8-11
//simple button GET with iframe code
//for use with IDE 1.0
//open serial monitor to see what the arduino receives
//use the \ slash to escape the " in the html
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields
#include <SPI.h>
#include <Ethernet.h>
byte rip[4];
//byte rip[] = {0,0,0,0};
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port
String readString;
//////////////////////
void setup(){
pinMode(4, OUTPUT); //pin selected to control
//start Ethernet
Ethernet.begin(mac, ip, gateway, subnet);
server.begin();
//enable serial data print
Serial.begin(9600);
Serial.println("server LED test 1.0"); // so I can keep track of what is loaded
}
void loop(){
// Create a client connection
EthernetClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();
//read char by char HTTP request
if (readString.length() < 100) {
//store characters to string
readString += c;
//Serial.print(c);
}
//if HTTP request has ended
if (c == '\n') {
///////////////
Serial.println(readString); //print to serial monitor for debuging
for (int bcount= 0; bcount < 4; bcount++)
{
Serial.print(rip[bcount], DEC);
if (bcount<3) Serial.print(".");
}
Serial.println();
//now output HTML data header
if(readString.indexOf('?') >=0) { //don't send new page
client.println("HTTP/1.1 204 Zoomkat");
client.println();
client.println();
}
else {
client.println("HTTP/1.1 200 OK"); //send new page
client.println("Content-Type: text/html");
client.println();
client.println("<HTML>");
client.println("<HEAD>");
client.println("<TITLE>Arduino GET test page</TITLE>");
client.println("</HEAD>");
client.println("<BODY>");
client.println("<H1>Zoomkat's simple Arduino button</H1>");
client.println("<a href=\"/?on\" target=\"inlineframe\">ON</a>");
client.println("<a href=\"/?off\" target=\"inlineframe\">OFF</a>");
//client.println("<IFRAME name=inlineframe src=\"res://D:/WINDOWS/dnserror.htm\" width=1 height=1\">");
client.println("<IFRAME name=inlineframe style=\"display:none\" >");
client.println("</IFRAME>");
client.println("</BODY>");
client.println("</HTML>");
}
delay(1);
//stopping client
client.stop();
///////////////////// control arduino pin
if(readString.indexOf("on") >0)//checks for on
{
digitalWrite(4, HIGH); // set pin 4 high
Serial.println("Led On");
}
if(readString.indexOf("off") >0)//checks for off
{
digitalWrite(4, LOW); // set pin 4 low
Serial.println("Led Off");
}
//clearing string for next read
readString="";
}
}
}
}
}
// the next function allows us to use the client returned by
// EthernetServer::available() as the condition in an if-statement.
EthernetClient::operator bool() {
return _sock != MAX_SOCK_NUM;
}
uint8_t *EthernetClient::getRemoteIP(uint8_t remoteIP[])
{
W5100.readSnDIPR(_sock, remoteIP);
return remoteIP;
}
You've not put the client.getRemoteIP(rip); line in to actually read the remote IP prior to printing it.
[color=red]client.getRemoteIP(rip); // this is the code that actually puts the IP into the variable rip[/color]
for (int bcount= 0; bcount < 4; bcount++)
{
Serial.print(rip[bcount], DEC);
if (bcount<3) Serial.print("."); else Serial.println();
}
samlro2:
I am a super newbee. I am not sure where to connected the ethernet cable if I want to get remote data from home. The router?
samlro2, your question isn't directly related to this topic, but I will help you out.
If you want to connect to your Arduino via a network or internet you will need to plug it into a router.
Then, from within the network, you can access the arduino simply by entering the arduino's IP into a browser (the IP you set within the sketch).
Connecting via the internet, things get a little more complicated:
First you will need to set up your router so it routes all port 80 requests to the arduino. google port forwarding and your router model.
Second you will need some way of contacting your router from the internet, your external IP address is likely to vary, so the best way is to get a domain name. google about dynamic domain name providers (i.e. dyndns, no-ip etc).
There are a few guides that go into a lot more detail and give full sketches. Google should be able to help there.
giampiero7: @karlok returning a variable declared in the local scope of a function is not the right thing to do.
The "pass by reference" method is the right one.
So is it to be understood,that it is still not possible to use the remoteIP() in official releases on incoming TCP connections, and somewhere someone is still pondering if it is I good idea to implement it, but no one can tell where it lands?
And that there are ways to implement it yourself, but it was loosely discussed which way was best and that didn't got settled either ?
fxfever:
, and somewhere someone is still pondering if it is I good idea to implement it, but no one can tell where it lands?
From the discussion on the attempt to add this function to the stock Ethernet library it seems it was definitely decided against, though I don't understand why. Of course it's been a while so it might be reconsidered if someone brought it up with good reasoning why the previous decision is wrong.
fxfever:
there are ways to implement it yourself, but it was loosely discussed which way was best and that didn't got settled either ?
I use the IPAddress return type because that's how it was done in the official EthernetUDP remoteIP() and is more user friendly but the "pass by reference" method will work fine also.