我尝试使用 C 语言使用 IPv6 和 UDP 制作客户端/服务器程序。当程序绑定套接字时,它返回 WSAError 10049。我知道这是地址名称的问题,但不知道问题是什么。我希望有人能帮忙。
struct sockaddr_in6 server, client;
SOCKET sock;
char buffer[BUFFERSIZE];
LPTSTR recvBuff[1024];
DWORD recvBuffLen = 1024UL;
int len = sizeof(client);
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(1,1);
WSAStartup(wVersionRequested, &wsaData);
sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock < 0)
error("Fehler beim Anlegen des Sockets");
server.sin6_family = AF_INET6;
server.sin6_port = htons(6000);
server.sin6_addr = in6addr_any;
if (bind(sock, (struct sockaddr *) &server, sizeof(server)) == -1)
error("Fehler beim binden des Sockets");
您应该在这里使用
PF_INET
而不是 AF_INET
。它们具有相同的值,但您在此不指定地址族 AF
,而是指定协议族 PF
。这只是一个风格推荐。
我建议
memset
将以下数组、结构归零:
struct sockaddr_in6 server, client;
SOCKET sock;
char buffer[BUFFERSIZE];
LPTSTR recvBuff[1024];
在使用
sockaddr_in6
结构之前,您必须将 memset
设置为零:
memset(server, 0, sizeof(struct sockaddr_in6));
原因是
struct sockaddr_in6
结构包含您未初始化的其他字段(例如 sin6_scope_id
)并且可能包含垃圾。
我也遇到过同样的错误。
@askMish 的回答很对。我一开始没明白,但后来我明白了。
这通常是由于尝试绑定到对本地计算机无效的地址而导致的..
通常我们的计算机位于某个网关下。
如果我们运行
ipconfig
,我们会发现IP地址是192.168.something。
这就是我们可以用来在代码中绑定的 IP。
而其他人应该连接公共IP(如果你可以上网,你肯定有一个。)比如47.93。如果他们与你在同一个局域网中的话。
您需要在您的网关上找到该IP(可能是您家人的路由)。
我在 Windows 下调用
bind()
时遇到相同的错误代码。
我的情况的原因与最初的海报代码中的原因不同,但我想其他人也会犯和我一样的错误:
我生成了本地地址,我希望使用
inet_addr()
函数将服务器本地绑定到该地址。
我将这个结果分配给本地地址结构struct sockaddr_in localaddr
这样:
localaddr.sin_addr.s_addr = htonl(inaddr);
但是
inet_addr()
已经以字节网络顺序返回地址,因此调用htonl(inaddr)
在我的代码中是错误的并导致错误10049:
SOCKET tcpsock_bindlisten(unsigned short port, const char* bindaddr)
{
SOCKET srvsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
unsigned long inaddr = bindaddr ? inet_addr(bindaddr) : INADDR_ANY;
struct sockaddr_in localaddr;
memset(&localaddr, 0, sizeof(struct sockaddr_in));
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(port);
// ERROR HERE! address returned from inet_addr is already in network-byte-order!
localaddr.sin_addr.s_addr = htonl(inaddr);
// CORRECT THIS WAY:
localaddr.sin_addr.s_addr = inaddr;
if (bind(srvsock, (struct sockaddr *) &localaddr, sizeof(localaddr)) != 0)
{
print_socketerror("tcpsock bind()");
return INVALID_SOCKET;
}
if (listen(srvsock, SVRSOCK_BACKLOG) != 0)
{
print_socketerror("tcpsock listen()");
return INVALID_SOCKET;
}
return srvsock;
}
当使用“所有本地接口”(
bind()
)调用INADDR_ANY
时,它起作用了,因为这个巧合INADDR_ANY == htonl(INADDR_ANY)
:
int main()
{
...
// this works for this special case:
SOCKET svrsock1 = tcpsock_bindlisten(4444, NULL);
// did not work!
SOCKET svrsock2 = tcpsock_bindlisten(5555, "192.168.0.123");
}
我认为问题可能在于 IPv6 的 UDP 协议规范。它是 IPv4。还要确保端口在您的系统上有效且处于活动状态。因此套接字定义应类似于以下示例
进口插座
udp_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) udp_socket.bind(('169.254.33.36',5353))