3

Presently I am in the midst of constructing a peer-to-peer network architecture and am at the stage of creating a receive function which will accept messages from multiple clients on the network. Essentially when the recvfrom function is called - the address of the most recent client to have sent a message to the main client is loaded into a sockaddr_in struct called fromAddr. The program is then designed to loop through a vector containing multiple instances of a client class (each of which hold the necessary information and functionality to represent a client on the network), and find the client instance whose sockaddr_in struct matches that of the just received message. In the program the evaluation currently looks like so:

void UDPClass::checkID(Message* mess, sockaddr_in fraeAddress)
{
sockaddr_in anAddr;
//Iterate through the vector of clients and find the one who sent the message
for(int i = 0; i < theClients.size(); i++)
{
    anAddr = theClients[i].getAddress();
    //if the address of the recieved message matches the address of the current client
    if((anAddr.sin_addr == fraeAddress.sin_addr) && (anAddr.sin_port == fraeAddress.sin_port))
    {
        //Update local instance of the client so that its location data matches that of the recieved message
        theClients[i].setX(mess->x);
        theClients[i].setY(mess->y);
    }
}
}

When the program is compiled the following error is reported:

Error 3 error C2678: binary '==' : no operator found which takes a left-hand operand of type 'IN_ADDR' (or there is no acceptable conversion)

As might be inferred I have also tried evaluating the expression by simply comparing the two sockaddr_in structs themselves:

if(anAddr == fraeAddress)

Which reports the same error. The question is: short of creating a sockaddr_in class with overloaded operator functions that would allow you to evaluate the expression, what would be the simplest way of implementing this comparison?

JonasVautherin
  • 7,297
  • 6
  • 49
  • 95
Enchanter
  • 117
  • 1
  • 10
  • Sounds like [`memcmp()`](http://en.cppreference.com/w/c/string/byte/memcmp) will help you out. Just comparing pointers like `if(anAddr == fraeAddress)` doesn't help much. – πάντα ῥεῖ Mar 20 '15 at 22:43
  • 1
    Overload the operator – arynaq Mar 20 '15 at 22:56
  • People who look at this in the future need to read the answer from o11c below re IPv6 issues vs IPv4 issues for this comparison. Be careful to understand how to do this for your use case. – Alan Mimms Sep 29 '22 at 20:48

2 Answers2

8

You may want to test the unsigned long members of in_addr like this:

if((anAddr.sin_addr.s_addr == fraeAddress.sin_addr.s_addr) && (anAddr.sin_port == fraeAddress.sin_port))

or for Windows:

if((anAddr.sin_addr.S_addr == fraeAddress.sin_addr.S_addr) && (anAddr.sin_port == fraeAddress.sin_port))
DNT
  • 2,356
  • 14
  • 16
  • Thanks - there are obviously many variables contained in the in_addr struct but will comparing the ulong variables of each in_addr equate to comparing the actual IP address - I suspect the IP address is contained in the 4 uchar variables. I'll give you're method a whirl though. – Enchanter Mar 21 '15 at 02:26
  • Those four uchar are in a union with the ulong (Microsoft), so the unsigned long takes the same space as they do. – DNT Mar 23 '15 at 11:06
1

Depending on how exactly your addresses originate, there are cases where a byte-comparison won't work: IPv4 addresses may be stored in either sockaddr_in or sockaddr_in6. sockaddr_in6 may or may not contain sin6_scope_id and sin6_flowinfo and alignment may vary.

Do you need only IPv4 and IPv6, or do you need to handle other kinds of sockets? (It is unforgivable to write IPv4-only programs these days.) If so (and maybe even if you do need to support unix, netlink, raw, or obscure socket types), I recommend converting all IP addresses to IPv6 and then using your own class for comparisons.

(Also you shouldn't use a linear search).

o11c
  • 15,265
  • 4
  • 50
  • 75
  • This framework is purely an academic exercise so it is not so imperative to use IPv6 in this case but thanks anyway. Even though the search is linear, I intend to eventually have the recieve function running on a thread all of its own. – Enchanter Mar 21 '15 at 02:17
  • @Enchanter in a purely academic exercise it is even more important to do these things right. And it's a bad design to use one-thread-per-socket, at most you want one-thread-per-CPU for load-balancing purposes. – o11c Mar 21 '15 at 19:37
  • Oh agree'd its important to do things right like not using one thread per socket - one thread per function - as in one function iterating through all the clients and sending the update packets to them continuously and one thread recieving packets and updating the locally stored clients accordingly and continuously. And its probably better having one thread per core - one thread per CPU implies one thread overall - you have one CPU containing many cores capable of running a thread each concurrently. – Enchanter Mar 21 '15 at 23:32
  • @Enchanter I'm using typical terminology in software land, e.g. quoting cpuset(7): "The CPUs of a system include all the logical processing units on which a process can execute, including, if present, multiple processor cores within a package and Hyper-Threads within a processor core." – o11c Mar 22 '15 at 07:53