When I assign this address , it says cannot assign requested address
. But when I put local address (127.0.0.1) it accepts it. Why???
char* hostname = "192.168.1.8";
int sockfd;
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
socklen_t addr_len;
int numbytes;
char buf[MAXBUFLEN];
int port =5000;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(1);
}
try
{
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_addr.s_addr = inet_addr(hostname);
printf("Accepted/n");
// automatically fill with my IP
my_addr.sin_port = htons(5000); // short, network byte order
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind");
exit(1);
}
while (1)
{
addr_len = sizeof(struct sockaddr);
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
(struct sockaddr *)&their_addr, &addr_len)) == -1) {
perror("recvfrom");
exit(1);
}
//printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr));
//printf("packet is %d bytes long\n",numbytes);
buf[numbytes] = '\0';
//printf("packet contains \"%s\"\n",buf);
}
close(sockfd);
}
catch(...)
{
If the error is happening on the bind
(it's not that obvious based on your question content since the error message you state does not appear in the code), it's likely to be because the address is not available.
That's usually because it's already in use, or not available on the current host.
With a few exceptions, you can generally only bind to IP addresses that are assigned to your local interfaces. You should check that 192.168.1.8
is in that class. It's a given that 127.0.0.1
will be a local interface (hence why it works), and that INADDR_ANY
will work as well - that's probably the "address" you should use unless you have a real specific need to limit yourself to one interface.
You should check the errno
following the failing function and match it against the possibilities.
As an aside, and this is probably irrelevant to your problem, the way in which you initialise the sockaddr_in
structure (setting fields then clearing the rest) seems to be less than portable to me.
I think it would be safer to clear the lot then simply set what you desire after that, something like:
memset (&my_addr, 0, sizeof (my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = inet_addr (hostname);
my_addr.sin_port = htons (5000);
At least that way, the order of fields within the structure won't affect your code.
You can see the problem with the following code. First off, the requisite headers:
#define __USE_GNU
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
Then the argument checking and socket creation.
int main (int argc, char *argv[]) {
int sockfd;
struct sockaddr_in me;
if (argc < 2) {
printf ("Need argument with IP address\n");
return 1;
}
if ((sockfd = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
return 1;
}
Then the binding itself:
memset (&me, 0, sizeof (me));
me.sin_family = AF_INET;
me.sin_addr.s_addr = inet_addr (argv[1]);
me.sin_port = htons (5000);
if (bind (sockfd, (struct sockaddr *)&me, sizeof(struct sockaddr)) == -1)
{
fprintf (stderr, "errno = %d ", errno);
perror("bind");
exit(1);
}
close(sockfd);
return 0;
}
When you run that with certain arguments, you can see it works okay for the ones where the IP addresses belong to local interfaces (127.0.0.1
and 192.168.0.101
) but not for those that do not, like 192.168.0.102
:
pax> ifconfig | grep 'inet addr'
inet addr:192.168.0.101 Bcast:192.168.0.255 Mask:255.255.255.0
inet addr:127.0.0.1 Mask:255.0.0.0
inet addr:192.168.99.1 Bcast:192.168.99.255 Mask:255.255.255.0
inet addr:192.168.72.1 Bcast:192.168.72.255 Mask:255.255.255.0
pax> ./testprog 127.0.0.1
pax> ./testprog 192.168.0.101
pax> ./testprog 192.168.0.102
errno = 99 bind: Cannot assign requested address
pax> grep '#define.*99' /usr/include/asm-generic/errno.h
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
And, from the link to the bind
man page above, we see:
EADDRNOTAVAIL
A nonexistent interface was requested or the requested address was not local.