如果错误发生在bind
(根据您的问题内容,这并不明显,因为您所说的错误消息没有出现在代码中),这可能是因为地址不可用。
这通常是因为它已在使用中,或者在当前主机上不可用。
除少数例外情况外,您通常只能绑定到分配给本地接口的 IP 地址。你应该检查一下192.168.1.8
就在那个班级。这是一个给定的127.0.0.1
将是一个本地接口(因此它可以工作),并且INADDR_ANY
也可以工作 - 这可能是您应该使用的“地址”,除非您确实有特定的需要将自己限制在一个接口上。
您应该检查errno
跟踪失败的函数并将其与可能性 http://linux.die.net/man/2/bind.
顺便说一句,这可能与您的问题无关,即您初始化的方式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 地址属于本地接口的 IP 地址运行正常(127.0.0.1
and 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
请求了不存在的接口或请求的地址不是本地的。