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!
ehensensAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
lhl60Connect With a Mentor Commented:
well I wouldn't use HTTP in the discovery

HTTP is meant for connection oriented stuff
I will suggest something like this:

Let your server listen for UDP packets on a "discover port"
and let it listen for TCP connects requests on a "production" port

on the client side
build a discovery routine

Send a UDP packet to the subnet (broadcast) on the "discover" port, the content can be something identifying the client (version,secret code....)

The server picks it up, and respond (UPD)  with  some previously agreed message content that allow your client to identify it as a valid server ( maybe even information about the production port, or some other useful information)

If a satisfactory answer to the broadcast arrives, within a reasonable timer limit. the client then  know the IP address of the server. and the client can initiate a normal  production connection (TCP).


0
 
mrjoltcolaCommented:
.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.
0
 
ehensensAuthor Commented:
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!
0
What Kind of Coding Program is Right for You?

There are many ways to learn to code these days. From coding bootcamps like Flatiron School to online courses to totally free beginner resources. The best way to learn to code depends on many factors, but the most important one is you. See what course is best for you.

 
mrjoltcolaCommented:
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));
0
 
mrjoltcolaCommented:
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
0
 
ehensensAuthor Commented:
So do I call setsockopt() , sendto() , write() , read() in that order?
0
 
mrjoltcolaCommented:
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.

0
 
mrjoltcolaCommented:
0
 
ehensensAuthor Commented:
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()"?
0
 
mrjoltcolaCommented:
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.
0
 
ehensensAuthor Commented:
Sorry, I guess I overlooked it. Let me give it a whirl!
0
 
ehensensAuthor Commented:
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

0
 
mrjoltcolaCommented:
Curious why you are broadcasting an HTTP POST.

Anyway, is your receiver showing anything, and is it responding?
0
 
ehensensAuthor Commented:
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...
0
 
mrjoltcolaConnect With a Mentor Commented:
broadcasting is connectionless, yes.

Typically you use it with UDP, then wait for responses, in packet mode, and the response can be from anyone. Stream mode won't work.

The POST you have is an HTTP request, which requires TCP level anyway. A listening TCP socket will never receive a broadcast, its impossible.
0
 
mrjoltcolaCommented:
Oh, sorry I did not see lhl60's response, he already explained.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.