Если ошибка возникает на bind
(это не так очевидно по содержанию вашего вопроса, так как сообщение об ошибке, которое вы указали, не появляется в коде), скорее всего, это связано с тем, что адрес недоступен.
Обычно это происходит потому, что он уже используется или недоступен на текущем хосте.
За некоторыми исключениями, вы, как правило, можете связывать только IP-адреса, назначенные локальным интерфейсам.Вы должны проверить, что 192.168.1.8
находится в этом классе.Принято считать, что 127.0.0.1
будет локальным интерфейсом (следовательно, почему он работает), и что INADDR_ANY
также будет работать - это, вероятно, «адрес», который вы должны использовать, если у вас нет реальной конкретной необходимости ограничивать себя одниминтерфейс.
Вы должны проверить errno
после сбойной функции и сопоставить ее с возможностями .
В сторону, и это, вероятно, не имеет значенияк вашей проблеме, способ инициализации структуры sockaddr_in
(установка полей, а затем очистка остальных) кажется мне менее чем переносимым.
Я думаю, что было бы безопаснее очистить лот, чем простоустановите желаемое после этого, что-то вроде:
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);
По крайней мере, порядок полей в структуре не повлияет на ваш код.
Вы можете видетьпроблема со следующим кодом.Прежде всего, необходимые заголовки:
#define __USE_GNU
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
Затем проверка аргументов и создание сокетов.
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;
}
Затем сама привязка:
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;
}
Когда вы запускаетечто с определенными аргументами вы можете видеть, что это работает нормально для тех, где IP-адреса принадлежат локальным интерфейсам (127.0.0.1
и 192.168.0.101
), но не для тех, которые этого не делают, например 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 */
И из ссылки на справочную страницу bind
выше мы видим:
EADDRNOTAVAIL
Запрошен несуществующий интерфейс или запрошенный адрес не является локальным.