Get IP Address of Anyone Connected to my Arduino set up as server

I started off with my Arduino Ethernet shield by making a simple LED flashing light controlled by the web browser. I posted the link on Facebook and the light started to flash a lot! I wanted to see the IP addresses of the people connecting, but I could not for the life of me figure out how to. Help?

If it matters, here is my code (adapted from the example Web Server included in the software)

/*
  Web  Server - Modified
 
 A simple web server that shows the value of the analog input pins.
 using an Arduino Wiznet Ethernet shield. 
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * Analog inputs attached to pins A0 through A5 (optional)
 
 created 18 Dec 2009
 by David A. Mellis
 modified 4 Sep 2010
 by Tom Igoe
 
 */

#include <SPI.h>
#include <Ethernet.h>
#define redLED 2

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAA, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1, 177 };
byte gateway[] = { 192,168,1, 1 };
byte subnet[] = { 255, 255, 0, 0 };

int foo = 0;
String newLine = "";
// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
Server server(80);
boolean redLEDmode = false;

void setup()
{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.begin(9600);
  pinMode(redLED ,OUTPUT); 
}

void loop()
{
  // listen for incoming clients
  Client client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
       // Serial.print(c);
        
       if (newLine.length() < 100){
         newLine.concat(c);
       }
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n'){
          //test if the string starts with GET
          byte rip[4];
         // Serial.print();
          Serial.print(rip[0]);
          Serial.print(".");
          Serial.print(rip[1]);
          Serial.print(".");
          Serial.print(rip[2]);
          Serial.print(".");
          Serial.print(rip[3]);
          Serial.print("\n");
          //Serial.print("line recieved\n");
          if(newLine.indexOf("GET")!= -1){
            Serial.print("get ");
            //see what "file" was requested
            if(newLine.indexOf("On") !=-1){
              Serial.print("ON\n");
              digitalWrite(redLED,HIGH);
              redLEDmode = true;
            }else if(newLine.indexOf("Off")!= -1){
              Serial.print("OFF\n");
              digitalWrite(redLED,LOW); 
              redLEDmode = false;
            }
            
            
          }
          
          
          if(currentLineIsBlank) {
            // send a standard http response header
           client.println("HTTP/1.1 200 OK"); 
           client.println("Content-Type: text/html");
           client.println();

           // output the value of each analog input pin
           client.print("<html><head><title>Arduino!!</title><script type=\"text/javascript\">");          
           client.print("function toggle(each){");
           // client.print("alert('th');");
           client.print("$.ajax({\ntype:'get',\nasync:true,\nurl:each});\n");
           client.print("$('#current').html(each);}");
           client.print("</script><script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\">");
           client.print("</script>");
           client.print("<body>");
           client.print("<div>Red LED is currently<span id=\"current\">");
          if(redLEDmode){
            client.print("ON");
           }else{
            client.print("OFF"); 
           }
           client.print("</span></div>");
           client.print("<input type=\"button\" onclick=\"toggle('On')\" value=\"Red LED On\" />");          
           client.print("<input type=\"button\" onclick=\"toggle('Off')\" value=\"Red LED Off\" />");
           client.print("<div id=\"test\"></div>");
           client.print("</body>"); 
           break;
          }
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
          newLine = "";
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }

}

This is something that I too am interested in learning how to do. If anyone has any info, that would be much appreciated! :slight_smile:

If you are using an Ethernet Shield with a W5100 chip, this seems to be possible to do... however, there isn't any library method programmed yet to do it in the Ethernet library.

If you download the W5100 manual and move down to page 31, you can see that the register Sn_DIPR holds the Destination IP address that can be written when in client mode or read when in server mode.

It's weekend now, so I won't have time for this. But maybe on Monday I can put together a function to test this and share with you guys.

Hello,

I just put up a method for this.
If you can follow my directions it's easy enough to do it. :slight_smile:

Find the files:

  • Resources\Java\libraries\Ethernet\Client.cpp
  • Resources\Java\libraries\Ethernet\Client.h

on the .cpp file add the following code

Client::Client(uint8_t *ip, uint16_t port) {
  _ip = ip;
  _port = port;  
  _sock = 255;
}

//what you need to add starts here
void Client::IP_address(uint8_t * addr)
{
	getSn_DIPR(_sock, addr);

}

Then on the .h file you should add:

void stop();
void IP_address(uint8_t * addr);//Only add this line as the others already exist
uint8_t connected();

Finally, a sketch made by me to test this could be:

/*
 * Web Server
 *
 * A simple web server that shows the value of the analog input pins.
 */

#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 67 };
byte client_ip[4];//added 

Server server(80);

void setup()
{
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{
  Client client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if we've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so we can send a reply
        if (c == '\n' && current_line_is_blank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          
          // output the value of each analog input pin
          for (int i = 0; i < 6; i++) {
            client.print("analog input ");
            client.print(i);
            client.print(" is ");
            client.print(analogRead(i));
            client.println("
");
          }
          
          client.IP_address(&client_ip[0]);//added 
          client.println("Your IP is:");//added 
          for (int n = 0; n<=3; n++)//added 
            {//added 
            client.print((int)client_ip[n]);//added 
            client.print(".");//added 
            }//added 
            
          break;
        }
        if (c == '\n') {
          // we're starting a new line
          current_line_is_blank = true;
        } else if (c != '\r') {
          // we've gotten a character on the current line
          current_line_is_blank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}

I hijacked the example as I'm not good with the Arduino syntax. I've added a tag on the lines I've written myself.
It is also possible to read the port and Mac Address of the device you're connected to, but since you define which port you listen to clients, that isn't so useful.

Thank you for your help and the example, but I just looked through my entire arduino folder and can not find either of those files. Could you give me an idea where I might find them? Thanks.

Jeremy

Hello,

I'm on Mac OSX.
If you search for those files in your computer, you can find them inside the Arduino folder. Just use search and you shouldn't have more than one copy of the files in your hard drive.

Jeremy-arduino:
Thank you for your help and the example, but I just looked through my entire arduino folder and can not find either of those files. Could you give me an idea where I might find them? Thanks.

Jeremy

On Mac OS X, applications are folders and the Arduino standard libraries are inside the Arduino application. Ctrl-Click on the Arduino app and select "Show Package Contents". From there: Resources->Java->libraries->Etherrnet

On my system I renamed Arduino.app v22 to Arduino22.app so the full path for me is:
/Applications/Arduino22.app/Contents/Resources/Java/libraries/Ethernet

The built-in libraries are read-only so to make changes you'll need to copy the Etherenet folder to a read-write flder. I think if you put a 'libraries' folder in your Home/Docuements/Arduino folder the libraries there will override the standard libraries?

@bubulindo
Very usefull addition to the ethernet lib, should be candidate for in a next release. Name could be more descriptive e.g.

void Client::getRemoteIPAddress(uint8_t * addr)

update:
just tried to run the sample program under win7 - IDE21 => two errors

  1. #include <SPI.h> should be added for version 19 and up
  2. 'getSn_DIPR' was not declared in this scope

The first was solved easily, do you know how to fix the second? Fixed!!

The second is to use the code below in Client.cpp

void Client::IP_address(uint8_t * addr)
{
W5100.readSnDIPR(_sock, addr); // replaces the getSn_DIPR(_sock, addr); V18 and below
}

Ok, well I am on Windows 7 and I have not directory structure like that. The closest thing I can find is this:
C:\Users\Jeremy\Desktop\arduino-0022\libraries\Ethernet\Ethernet.cpp
C:\Users\Jeremy\Desktop\arduino-0022\libraries\Ethernet\Ethernet.h

I did do the edit on those files but I might not have put the code in the right spot because I got an error on compile:
sketch_mar07a.cpp: In function 'void loop()':
sketch_mar07a:47: error: 'class Client" has no member named 'IP_address'

I even closed all the sketch windows and save the files and then restarted the Arduino sketch. Is there a certain spot that the code needs to go in the files?

Jeremy

johnwasser:

Jeremy-arduino:
Thank you for your help and the example, but I just looked through my entire arduino folder and can not find either of those files. Could you give me an idea where I might find them? Thanks.

Jeremy

On Mac OS X, applications are folders and the Arduino standard libraries are inside the Arduino application. Ctrl-Click on the Arduino app and select "Show Package Contents". From there: Resources->Java->libraries->Etherrnet

On my system I renamed Arduino.app v22 to Arduino22.app so the full path for me is:
/Applications/Arduino22.app/Contents/Resources/Java/libraries/Ethernet

The built-in libraries are read-only so to make changes you'll need to copy the Etherenet folder to a read-write flder. I think if you put a 'libraries' folder in your Home/Docuements/Arduino folder the libraries there will override the standard libraries?

Did you actually read through the thread?
I, the guy that wrote the software change, am on Mac OSX. I know exactly where the files are, as I showed on my post. I do not know, however, where those files might be located in Windows or Linux Operating Systems, which appear to be the problem Jeremy is having.

About the addition in the Ethernet lib, go ahead. There's a few more functions coded in the w5100.c file that could be mapped to the C++esque world, but this one is actually quite useful. :slight_smile:

Jeremy-arduino:
Ok, well I am on Windows 7 and I have not directory structure like that. The closest thing I can find is this:
C:\Users\Jeremy\Desktop\arduino-0022\libraries\Ethernet\Ethernet.cpp
C:\Users\Jeremy\Desktop\arduino-0022\libraries\Ethernet\Ethernet.h

I did do the edit on those files but I might not have put the code in the right spot because I got an error on compile:
sketch_mar07a.cpp: In function 'void loop()':
sketch_mar07a:47: error: 'class Client" has no member named 'IP_address'

I even closed all the sketch windows and save the files and then restarted the Arduino sketch. Is there a certain spot that the code needs to go in the files?

Jeremy

Ups... I'm on Arduino-18. :S LOL
Do you know where I can have a look at those Ethernet.c and .h files?

Do you want to download from Arduino or the exact files that I am using?
Arduino download here: http://arduino.cc/en/Main/Software
My Ethernet.h: http://www.towerboy.com/arduino/Ethernet.h
My Ethernet.cpp: http://www.towerboy.com/arduino/Ethernet.cpp

Jeremy

Jeremy-arduino:
Do you want to download from Arduino or the exact files that I am using?
Arduino download here: http://arduino.cc/en/Main/Software
My Ethernet.h: http://www.towerboy.com/arduino/Ethernet.h
My Ethernet.cpp: http://www.towerboy.com/arduino/Ethernet.cpp

Jeremy

I was referring to the files as I'm not interested in downloading a new Arduino version.
And if these are your files, I'm sorry to say that they must be present, otherwise you shouldn't be able to compile.
In the Ethernet.h you have the following lines:

#include "Client.h"
#include "Server.h"

Which means that the files are on the same folder as the Ethernet.h file is. :\
Did you run a search on Windows? Isn't there any file named like these two on your computer?

On my Windows 7 device the Client.[cpp|h] file can be found @

~arduino-0022\libraries\Ethernet\Client.cpp
~arduino-0022\libraries\Ethernet\Client.h

@Robtillaart

Thanks, like I said before, I haven't got the latest Arduino environment (because I mostly program in C), but because this was something I was doing in my implementation with the Ethernet shield, I decided to have a go at C++ and add it to the Arduino interface.

Thanks again for the correction and improvements, one thing I did in my projects was:

typedef struct {
unsigned char address[4];
unsigned int port;
} IP;

That would be quite useful to describe IP addresses and the method we built could have a call to getSn_DPORT() or, W5100.readSnDPORT(_sock), so that we get a complete description of the client's address.
I think the MAC address would be overkill though.

OK, I feel like the village idiot... Yes, I was looking for and gave you the wrong files... Here are the correct ones...
http://www.towerboy.com/arduino/Client.h //Removed from my server now.
http://www.towerboy.com/arduino/Client.cpp //Removed from my server now.

I made the changes to them and I still get the same error as before:

sketch_mar07a.cpp: In function 'void loop()':
sketch_mar07a:47: error: 'class Client' has no member named 'IP_address'

Any ideas? I am using the arduino uno if that makes a difference...

Jeremy

maybe i messed something up, because now I can't compile anything with Ethernet.h in it... overwriting messed up files now...

Jeremy

After modifying files you might need to restart all instances of the IDE.

Which version of the IDE are you using?

Rob

OK, here is what I have now... It took me a while to figure out that in your snippets of the .h and .cpp file I was supposed to find some of the text and add the pertinant stuff right after it... Got that done now. I am running Ver0022 and yes, every time I make a change to the files, I close and reopen all the Arduino IDE's. When I compile now, this is what I get:

C:\Users\Jeremy\Desktop\arduino-0022\libraries\Ethernet\Client.cpp: In member function 'void Client::IP_address(uint8_t*)':
C:\Users\Jeremy\Desktop\arduino-0022\libraries\Ethernet\Client.cpp:26: error: 'getSn_DIPR' was not declared in this scope

???

Jeremy

@ Jeremy :

See my previous post, but here again:
The ethernet lib changed in version 19. The patch proposed here was for version 18.


  1. #include <SPI.h> should be added for version 19 and up
  2. 'getSn_DIPR' was not declared in this scope

The first was solved easily, do you know how to fix the second? Fixed!!
The second is to use the code below in Client.cpp

void Client::IP_address(uint8_t * addr)
{
W5100.readSnDIPR(_sock, addr); // replaces the getSn_DIPR(_sock, addr); V18 and below
}

Hopes this helps,
Rob