Link to home
Start Free TrialLog in
Avatar of ehensens
ehensensFlag for United States of America

asked on

c++ connect() permission denied, why?

Hi all,

I have a c++ client that communicates with a service on a small network. I am trying to let the user find the IP address of the service by sending a message to a broadcast IP address, to which my service will respond, etc. I don't think I am doing this correctly, however...

The IP of the service is 192.168.1.102
The subnet mask is 255.255.255.0

As far as I could tell, the corresponding broadcast would be 192.168.1.255, is that right? Well, when I try to connect() to that IP address, it always comes back with errno 13 Permission denied. Does anyone have any idea why this is happening or better yet how I can properly send out one single message to every IP my service could possibly be on?

Thank you!
Avatar of mrjoltcola
mrjoltcola
Flag of United States of America image

.255 would be the broadcast address, but it is not a single IP/interface so you can't "connect" to it.

To broadcast you don't need to connect, you just need to open a socket from an interface and send to the broadcast address.
Avatar of ehensens

ASKER

Hi mrjoltcola,

Thank you for your response. I'm afraid I don't quite understand what you mean that I don't need to connect to it. How do I send to the broadcast address without connecting?

Thanks again!
For example, with sendto() and UDP, you won't use connect(), you just use sendto().

Using the Berkeley socket call, sendto() allows you to pass the sockaddr structure in as the 5th argument, along with the address len. That is what differentiates sendto() from send() which operates on a connected socket.

You can use connect() on UDP sockets, but only if it is a valid IP address, which .255 and .0 are not. And connect() is only needed if you wish to then use send() without passing the 5th and 6th arguments as with sendto(). It might speed up things a bit, and make your socket code less cluttered, and I use it when I can in UDP programming.

Note the difference:

  ssize_t send(int s, const void *buf, size_t len, int flags);
  ssize_t sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);

In your case, just pass the address, something like this, where toaddr is a "struct sockaddr" that contains the .255 network broadcast address.

sendto(fd, &datastruct, sizeof(datastruct), flags, &toaddr, sizeof(sockaddr));
You also need to use setsockopt(fd, SOL_SOCKET, SO_BROADCAST, ... ) or you may also get permission denied. This is from W. Richard Stevens book, _UNIX Network Programming_ which is probably the best single book you can own if you write networking software.

Even if using Windows, the old Berkeley sockets API still applies, mostly, so the book is very relevant and has a complete chapter on Broadcasting.

http://www.amazon.com/UNIX-Network-Programming-Networking-Sockets/dp/013490012X
So do I call setsockopt() , sendto() , write() , read() in that order?
That is the order, but sendto is in place of write, and recvfrom/recv is in place of read. No need for both. write cannot write to broadcast addresses, that I know of, as it just uses a descriptor, and since you cannot obtain a "connected descriptor" to a broadcast adderss, you cannot use write.

Those are both great links but I don't see how the sender receives the response? Before I was just connect(), write(), and then read()

since i'm not doing connect() or write() now, just sendto(), how do I do the equivalent of "read()"?
The sender would receive the response by calling recv on the socket. You can bind to that socket, and read from it. The 2nd link I provided does discuss that in the last message.
Sorry, I guess I overlooked it. Let me give it a whirl!
It just sits on recv() seemingly forever, I don't see what I'm doing wrong, do you?

    struct hostent *hostentPointer;
    
    hostentPointer = gethostbyname(broadcastHost);
   
    struct sockaddr_in serverAddress;
    
    char **pPointer;
    char networkAddress[A_NUMBER];
    
    int broadcast = 1;
       
    hostentPointer = gethostbyname(broadcastHost);
       
    pPointer = hostentPointer -> h_addr_list;
    
    inet_ntop(hostentPointer->h_addrtype, *pPointer, networkAddress, sizeof(networkAddress));
    
    int sockFD = socket(PF_INET, SOCK_DGRAM, 0);
    
    setsockopt(sockFD, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
    
    bind(sockFD, (struct sockaddr*) &serverAddress, sizeof(serverAddress));
   
    bzero(&serverAddress, sizeof(serverAddress));
    serverAddress.sin_family = PF_INET;
    serverAddress.sin_port = htons(8004);
    inet_pton(AF_INET, networkAddress, &serverAddress.sin_addr);
 
    char sendRequest[SENDSIZE];
 
    char payload[SOME_NUMBER] = "";
        
    strcat(payload, "broadcastFunction");
    
    snprintf(sendRequest, BUFFSIZE,
            
             /* Actual HTTP POST text */
             "POST %s HTTP/1.0\r\n"
             "Host: %s\r\n"
             "Content-type: text/plain\r\n"
             "Content-length: %d\r\n\r\n"
             "%s", "Directory", broadcastHost, strlen(payload), payload);
    
 
 
    sendto(sockFD, sendRequest, strlen(sendRequest), 0, (struct sockaddr *) &serverAddress, sizeof(serverAddress));
 
 
    unsigned int msgLength = 10000;
   
    recv(sockFD, broadcastResponse, msgLength, 0);
    
    
    printf("\n\nBroadcast response:\n\n%s\n", broadcastResponse);

Open in new window

Curious why you are broadcasting an HTTP POST.

Anyway, is your receiver showing anything, and is it responding?
ASKER CERTIFIED SOLUTION
Avatar of lhl60
lhl60

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Sorry if my code is a little perplexing, I am brand new to networking. I've been POSTing information from my app to my service under normal running conditions, so I thought that for any kind of automatic "Find Service IP Address" feature I'd just do the same thing, only use a broadcast IP address instead of the service's specific IP. Then I found out that you can't connect() to a broadcast IP... I guess I'll just have to try to sludge through this...

I've gotten to the point where I can finally recv() from that socket now after I sendto() but it's just reading exactly what I sent, and my service is not responding. It seems I can only get my service to acknowledge communication when I write() to it...
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Oh, sorry I did not see lhl60's response, he already explained.