Like Tree1Likes
  • 1 Post By MK27

struct problems storing IP

This is a discussion on struct problems storing IP within the C Programming forums, part of the General Programming Boards category; Hi everyone, I got stuck again, this time with a different problem though. Writing on a little chat server based ...

  1. #1
    Registered User
    Join Date
    Sep 2011
    Posts
    6

    struct problems storing IP

    Hi everyone,
    I got stuck again, this time with a different problem though. Writing on a little chat server based on “Beej’s Guide to Network Programming” and I tried to save each incoming connection into an array, so that every time a client posts something that it also will echo the clients IP-address.
    For example:
    127.0.0.1: Hello, anybody out there?

    I got everything working but right now I just display following output:
    Socket 4: Hello, anybody out there?

    So in order to store the IP addresses as soon as a client connects, I created following struct.

    Code:
    struct connection
    {
    	const char *IPv4_addr;
    };
    And created an array variable of type struct connection;
    Code:
    struct connection client[6];	// client information
    Then I try to store the client IP in this array and I use the following command:
    Code:
    client[newfd].IPv4_addr=inet_ntop(remoteaddr.ss_family,get_in_addr((struct sockaddr*)&remoteaddr),remoteIP, INET_ADDRSTRLEN);
    Here is the function it is in
    Code:
    //----------------------------------------------------------
    // CHECK EXISTING CONNECTIONS FOR DATA
    //------------------------------------
    for(i = 0; i <= fdmax; i++)
    {
    	//------------------------------------------------------
    	// CHECK FOR NEW CONNECTIONS
    	//--------------------------
    	if (FD_ISSET(i, &read_fds))				// we got one!!
    	{ 
    		if (i == listener)
    		{
    			// handle new connections
    			addrlen = sizeof remoteaddr;
    			newfd = accept(listener,(struct sockaddr *)&remoteaddr,&addrlen);
    			if (newfd == -1)				// If connection attempt fails
    			{
    				perror("accept");
    			}
    			else
    			{
    				FD_SET(newfd, &master);		// add to master set
    				if (newfd > fdmax)			// keep track of the max
    				{
    					fdmax = newfd;
    				}
    			client[newfd].IPv4_addr=inet_ntop(remoteaddr.ss_family,get_in_addr((struct sockaddr*)&remoteaddr),remoteIP, INET_ADDRSTRLEN);
    			printf("selectserver: new connection from %s on socket %d\n",
    	/* -> */	inet_ntop(remoteaddr.ss_family,get_in_addr((struct sockaddr*)&remoteaddr),remoteIP, INET6_ADDRSTRLEN),newfd);
    			}
    		}
    And right in that line where it says:
    Code:
    client[newfd].IPv4_addr=inet_ntop(remoteaddr.ss_family,get_in_addr((struct sockaddr*)&remoteaddr),remoteIP, INET_ADDRSTRLEN);
    Is my problem, since I’m using a pointer and it always clear the entire content of that variable as soon as another client connects because it keeps pointing to the same spot in the memory. It works perfectly fine for a single connection (of course…..)
    Now I unfortunately can’t change it, since the function I use in that same line requires a pointer at that time I call it.
    So what else could I do, to bypass this problem and somehow store each clients IP-address in that client array of type struct connection?

    I hope You understand what exactly my problem is.
    The entire code is attached in a .zip file.


    I really hope you guys can help me out and I’d appreciate each suggestion that leads me the right way, since this is bugging me for a few days now.

    Thanks,
    ~Stud
    clean_print.c

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    You infer that "remoteIP" is a global buffer or something, that is your problem. You need to allocate a new buffer there for each connection, otherwise everyone's "IPv4_addr" will point to the same thing.

    The same thing said differently: inet_ntop() just returns the address of "remoteIP". If "remoteIP" is always the same buffer, inet_ntop() will always return the same "IPv4_addr".
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Sep 2011
    Posts
    6
    Hi,
    and thx for the fast reply.
    remoteIP returns the IP of the client that is currently "connecting"
    so if a new client connects it returns that IP.
    I made a test and connected first from localhost , then I connected from a remote machine on the same network. each time I printed the contents of both array variables. following scheme

    1. localhost, got Socket 4
    output on screen:
    client[4].IPv4_addr: 127.0.0.1
    client[5].IPv4_addr: (null)

    then I connected with the remote machine
    2. remotehost, got Socket 5
    output on screen:
    client[4].IPv4_addr: 192.168.1.3
    client[5].IPv4_addr: 192.168.1.3

    So it overwrote both this time,
    and it will do it the opposite way if I connect the remotehost first and then the localhost :-(

    I think my problem is within the struct
    Code:
    struct connection
    {
    	const char *IPv4_addr;
    };
    but if I remove the asterix it doesn't compile,
    it gives me error:
    assignment of read-only member IPv4_addr

    Any other ideas?
    Thanks in advance!!

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by studiologe View Post
    remoteIP returns the IP of the client that is currently "connecting"
    No. I have not seen a declaration or definition for "remoteIP", so I am looking at the context here:

    Code:
    inet_ntop(remoteaddr.ss_family,get_in_addr((struct sockaddr*)&remoteaddr),remoteIP, INET_ADDRSTRLEN)
    inet_ntop() is not a C standard function, but it is POSIX.

    inet_ntop

    From that, the prototype for inet_ntop():
    const char *inet_ntop(int af, const void *restrict src,
    char *restrict dst, socklen_t size);
    The dst argument points to a buffer into which the function stores the numeric address
    So either you are plugging in the wrong thing, or remoteIP is a char pointer. Pointers do not "return" anything. Things are returned into them. If you are doing what I am sure you are doing, you are returning information into the same address repeatedly, and then believing because you have done it over again this is some different address. It is not. It is still the same address, the address of remoteIP. You then assign that address to multiple variables, but they all point to the same place, remoteIP. And that keeps getting over-written.
    Last edited by MK27; 09-22-2011 at 09:46 PM.
    stahta01 likes this.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Did you try removing the const modifier from your struct?

    I don't think accept returns quite what you think it does.
    Accept does not return sequential number... it returns a Socket Handle which might be any value.
    Thus, client[newfd] is just as likely to be referencing the moon as your 6 element array.

  6. #6
    Registered User
    Join Date
    Sep 2011
    Posts
    6
    Hi and thanks for the detailed explanation @MK27.
    I see my problem, and that is actually what I thought is my problem, but I unfortunately don't know how to fix it the propper way.
    Well looking at the prototype of inet_ntop explains a lot.
    So I'm wondering how I could fix it in an appropriate way.
    One way I know right now is only following:
    create 10 variables from type struct connection
    Code:
    struct connection client1, client2, client3, ..., client10;
    and then check in the same if-statement where
    Code:
    client[newfd].IPv4_addr=inet_ntop(remoteaddr.ss_family,get_in_addr((struct sockaddr*)&remoteaddr),remoteIP, INET_ADDRSTRLEN);
    is right now and change that to something like:

    Code:
    if (newfd == 4) {
    client1.IPv4_addr=inet_ntop(remoteaddr.ss_family,get_in_addr((struct sockaddr*)&remoteaddr),remoteIP, INET_ADDRSTRLEN);
    }
    if (newfd == 5) {
    client2.IPv4_addr=inet_ntop(remoteaddr.ss_family,get_in_addr((struct sockaddr*)&remoteaddr),remoteIP, INET_ADDRSTRLEN);
    }
    ....
    if (newfd == 10) {
    client7.IPv4_addr=inet_ntop(remoteaddr.ss_family,get_in_addr((struct sockaddr*)&remoteaddr),remoteIP, INET_ADDRSTRLEN);
    }
    Of course that would be "the wrong way" and I could only handle n (10 in this case) clients.

    So I'd like to stick to that array of client variables of type struct connection, but don't know how to manage it.

    Do I have to do some kind of cast here, in order to make it work and change the struct connection itself into following:
    Code:
    struct connection {
    const char IPv4_addr;   //instead of *IPv4_addr
    };
    But how would I handle then the rest ?

    I'm really lost here, and doesn't have to do with being Friday night, beer and party mood :-/

    Please push my thoughts into the right direction!
    Thanks so far
    ~Stud

  7. #7
    Registered User
    Join Date
    Sep 2011
    Posts
    6
    Any other suggestions?

    I tried to remove the * in my struct and then do a cast when writing
    into the variable client[n] (of type struct connection), but it didn't work.

    PLEASE I need some help to get this working.

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    If you don't care which socket your users are connected on it gets a lot easier...

    Use a struct struct to include the socket handle and IP address (which is far easier to store as a dword value)

    Make an array of, say, 100 of these structs.
    When a user connects find an empty slot in the array and assign it to your user.
    To find a user... search for the IP to find the socket handle
    To find out who's on a socket... search for the socket to find the IP
    When a user disconnects set the socket handle to some impossible value (-1 or such) to mark it as empty.

    No high water marks, no need for specific slots, no problem searching for things...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Storing matrix positions and using them in a struct?
    By litzkrieg in forum C Programming
    Replies: 2
    Last Post: 08-29-2011, 04:08 PM
  2. 2 problems: Struct array and pointer + struct
    By v1n1c1u5 in forum C Programming
    Replies: 0
    Last Post: 12-13-2009, 05:38 PM
  3. storing into an ARRAY OF STRUCT
    By jave in forum C Programming
    Replies: 5
    Last Post: 10-23-2005, 03:25 AM
  4. problems storing values in varibles
    By stodd04 in forum C Programming
    Replies: 7
    Last Post: 02-08-2005, 11:56 AM
  5. storing struct ??!!ˇÖˇŐ
    By Unregistered in forum C Programming
    Replies: 1
    Last Post: 10-24-2001, 10:23 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21