tags:

views:

83

answers:

2

Hello.

I have two machines I'm testing my code on, one works fine, the other I'm having some problems and I don't know why it is.

I'm using an object (C++) for the networking part of my project. On the server side, I do this: (error checking removed for clarity)

     res = getaddrinfo(NULL, port, &hints, &server)) < 0

     for(p=server; p!=NULL; p=p->ai_next){
             fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
             if(fd<0){
                     continue;
                     }

             if(bind(fd, p->ai_addr, p->ai_addrlen)<0){
                     close(fd);
                     continue;
                     }
             break;
             }

This all works. I then make an object with this constructor

net::net(int fd, struct sockaddr *other, socklen_t *other_len){
        int counter;
         this->fd = fd;
         if(other != NULL){
                 this->other.sa_family = other->sa_family;
                 for(counter=0;counter<13;counter++)
                         this->other.sa_data[counter]=other->sa_data[counter];
                 }
         else
                 cerr << "Networking error" << endl;
         this->other_len = *other_len;
         }

 void net::gsend(string s){   
         if(sendto(this->fd, s.c_str(), s.size()+1, 0, &(this->other), this->other_len)<0){
                 cerr << "Error Sending, " << s << endl;
                 cerr << strerror(errno) << endl;
                 }
         return;
         }

  string net::grecv(){
         stringstream ss;
         string s;
         char buf[BUFSIZE];
         buf[BUFSIZE-1] = '\0';

         if(recvfrom(this->fd, buf, BUFSIZE-1, 0, &(this->other), &(this->other_len))<0){
                 cerr << "Error Recieving\n";
                 cerr << strerror(errno) << endl;
                 }

         // convert to c++ string and if there are multiple trailing ';' remove them
         ss << buf;
         s=ss.str();
         while(s.find(";;", s.size()-2) != string::npos)
                 s.erase(s.size()-1,1);
         return s;
         }    

So my problem is, is that on one machine, everything works fine. On another, everything works fine until I call my server's gsend() function. In which I get a "Error: Network Unreachable." I call gercv() first before calling gsend() too. Can anyone help me? I would really appreciate it.

SOLUTION

It turns out that the server didn't like the way I set up the initial sockaddr structure. I was doing this:

     struct addrinfo hints;
     memset(&hints, 0, sizeof(struct addrinfo));
     hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = SOCK_DGRAM;
     hints.ai_flags = AI_PASSIVE;
     hints.ai_protocol = IPPROTO_UDP;

When it should have been like this

     struct addrinfo hints;
     memset(&hints, 0, sizeof(struct addrinfo));
     hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = SOCK_DGRAM;

Can anyone explain this?

A: 

Few things to check 1. Run the server. Use netstat and see the IP and the port that the server is bound to. Is the IP a localhost IP or the 0.0.0.0 IP ? 2. Once you know that the server is listening on the right port and that the address is fine, check if you can telnet to the port. Just try this telnet 3. This will attempt a connection to the port (doesn't matter that it is not a telnet server, you can use this to check connectivity) 4. If telnet is able to connect to the port i.e. no errors, you can then check the client code to see what you are missing. And like Glen mentioned, did you check you are able to make remote connections from the client machine ?

Gangadhar
A: 

It seems that you are picking the interface that your server listens on by selecting the first interface that you can both create a socket for and bind to? This seems a novel way to do it...

Surely, on a machine with multiple NICs you are quite likely to want to bind to one rather than another and you're likely to KNOW which one you want; for example, if we have 2 NICs, one facing the internet and one facing an internal private network you probably know which interface you want to bind to and provide your service on and what your code appears to be doing is just selecting the first that it can both create a socket for and bind to...

Anyway, I would imagine that on the machine that you cant send from you're binding to an interface that is pointing at a network that doesn't have connectivity to your target address... Since you say you can receive data on that socket and from the code snippet I assume that you're trying to send back to the address you just received from it looks like the routing table of the machine that you're running on when you're having problems is setup incorrectly and that it can't route from itself to the target machine but the target machine CAN route to the server...

Len Holgate