bind 函数 (winsock.h)
bind 函数将本地地址与套接字相关联。
语法
int bind(
[in] SOCKET s,
const sockaddr *addr,
[in] int namelen
);
参数
[in] s
标识未绑定套接字的描述符。
addr
指向要分配给绑定套接字 的本地地址 的 sockaddr 结构的指针。
[in] namelen
addr 指向的值的长度(以字节为单位)。
返回值
如果未发生错误, 绑定 将返回零。 否则,它将返回SOCKET_ERROR,并且可以通过调用 WSAGetLastError 来检索特定的错误代码。
错误代码 | 含义 |
---|---|
注意 在使用此函数之前,必须成功调用 WSAStartup 。
|
|
网络子系统发生故障。 | |
试图以套接字访问权限所禁止的方式访问套接字。
如果 nn 尝试将数据报套接字绑定到广播地址失败,因为 未启用 setsockopt 选项SO_BROADCAST,则返回此错误。 |
|
通常每个套接字地址只允许使用一次(协议/网络地址/端口)。
如果计算机上的进程已绑定到相同的完全限定地址,并且套接字尚未标记为允许使用 SO_REUSEADDR 重用地址,则返回此错误。 例如, name 参数中指定的 IP 地址和端口已绑定到另一个应用程序正在使用的另一个套接字。 有关详细信息,请参阅SOL_SOCKET套接字选项参考中的 SO_REUSEADDR套接字选项 、 使用SO_REUSEADDR和SO_EXCLUSIVEADDRUSE和 SO_EXCLUSIVEADDRUSE。 |
|
请求的地址在其上下文中无效。
如果 name 参数指向的指定地址不是此计算机上的有效本地 IP 地址,则返回此错误。 |
|
系统尝试在调用中使用指针参数时检测到指针地址无效。
如果 name 参数为 NULL,name 或 namelen 参数不是用户地址空间的有效部分, namelen 参数太小, name 参数包含关联的地址系列地址格式不正确,或者 name 指定的内存块的前两个字节与与套接字描述符关联的地址系列 不匹配,则返回此错误。 |
|
阻止 Windows 套接字 1.1 调用正在进行,或者服务提供商仍在处理回调函数。 | |
提供的参数无效。
如果 套接字 已 绑定到地址,则返回此错误。 |
|
通常, WSAENOBUFS 指示没有足够的临时端口来为绑定分配。 | |
某个操作尝试对非套接字执行操作。
如果 s 参数中的描述符不是套接字,则返回此错误。 |
注解
在未连接的套接字上需要 绑定 函数,然后才能对 侦听 函数进行后续调用。 它通常用于绑定到面向连接的 (流) 或无连接 (数据报) 套接字。 绑定函数还可用于绑定到原始套接字, (套接字是通过调用类型参数设置为 SOCK_RAW) 的套接字创建的。 在后续调用 connect、ConnectEx、WSAConnect、WSAConnectByList 或 WSAConnectByName 函数之前,还可以在未连接的套接字上使用绑定函数,然后再发送操作。
使用调用套接字函数创建 套接字 时,它存在于命名空间 (地址系列) 中,但它没有为其分配名称。 使用 bind 函数通过将本地名称分配给未命名的套接字来建立套接字的本地关联。
使用 Internet 地址系列时,名称由三个部分组成:
- 地址系列。
- 主机地址。
- 标识应用程序的端口号。
在 Windows 套接字 2 中, 名称 参数不会严格解释为指向 sockaddr 结构的指针。 它以这种方式强制转换,以便与 Windows 套接字 1.1 兼容。 服务提供商可以随意将其视为 指向名称大小内存块的指针。 此块中的前 2 个字节 (对应于 sockaddr 结构的sa_family成员、sockaddr_in 结构的sin_family成员或sockaddr_in6结构的sin6_family成员) 必须包含用于创建套接字的地址系列。 否则,会发生错误 WSAEFAULT。
如果应用程序不关心分配的本地地址,请在 name 参数的 sa_data 成员中指定 IPv4 本地地址的常量值INADDR_ANY或 IPv6 本地地址的常量值in6addr_any。 这样,基础服务提供商就可以使用任何适当的网络地址,在 多宿主 主机 (即具有多个网络接口和地址) 的主机的情况下,可能会简化应用程序编程。
对于 TCP/IP,如果端口指定为零,则服务提供商会从动态客户端端口范围向应用程序分配唯一端口。 在 Windows Vista 及更高版本中,动态客户端端口范围是介于 49152 和 65535 之间的值。 这与 Windows Server 2003 及更早版本不同,其中动态客户端端口范围是介于 1025 和 5000 之间的值。 可以通过在以下注册表项下设置值来更改客户端动态端口范围的最大值:
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
MaxUserPort 注册表值设置要用于动态客户端端口范围最大值的值。 必须重启计算机才能使此设置生效。
在 Windows Vista 及更高版本上,可以使用 netsh 命令查看和更改动态客户端端口范围。 动态客户端端口范围可以针对 UDP 和 TCP 以及 IPv4 和 IPv6 进行不同的设置。 有关详细信息,请参阅 知识库929851。
应用程序可以在调用 bind 后使用 getsockname 来了解已分配给套接字的地址和端口。 如果 Internet 地址等于 INADDR_ANY 或 in6addr_any,则在连接套接字之前 ,getsockname 不一定提供地址,因为如果主机是多宿主的,则多个地址可能有效。 对于客户端应用程序,不建议绑定到除端口 0 以外的特定端口号,因为存在与本地计算机上已使用该端口号的另一个套接字发生冲突的危险。
对于多播操作,首选方法是调用 绑定 函数以将套接字与本地 IP 地址相关联,然后加入多播组。 尽管此操作顺序不是必需的,但强烈建议这样做。 因此,多播应用程序将首先在本地计算机上选择 IPv4 或 IPv6 地址、通配符 IPv4 地址 (INADDR_ANY) ,或者通配符 IPv6 地址 (in6addr_any) 。 然后,多播应用程序将使用 name 参数的 sa_data 成员中的 此地址调用绑定函数,以将本地 IP 地址与套接字相关联。 如果指定了通配符地址,则 Windows 将选择要使用的本地 IP 地址。 绑定函数完成后,应用程序将加入感兴趣的多播组。 有关如何加入多播组的详细信息,请参阅多 播编程部分。 然后,可以使用此套接字通过 recv、recvfrom、WSARecv、WSARecvEx、WSARecvFrom 或 LPFN_WSARECVMSG (WSARecvMsg) 函数从多播组接收多播数据包。
将操作发送到多播组通常不需要 绑定 函数。 如果套接字尚未绑定, sendto、WSASendMsg 和 WSASendTo 函数会将套接字隐式绑定到通配符地址。 在使用发送或WSASend 函数之前,需要绑定函数,这些函数不执行隐式绑定,并且仅在连接的套接字上允许,这意味着必须已绑定套接字才能连接。 如果应用程序想要在具有多个网络接口和本地 IP 地址的本地计算机上选择特定的本地 IP 地址,则可以在使用 sendto、WSASendMsg 或 WSASendTo 函数的发送操作之前使用绑定函数。 否则,使用 sendto、WSASendMsg 或 WSASendTo 函数隐式绑定到通配符地址可能会导致不同的本地 IP 地址用于发送操作。
IrDA 套接字说明
- 必须显式包含 Af_irda.h 头文件。
- 本地名称不会在 IrDA 中公开。 因此,IrDA 客户端套接字不得在 connect 函数之前调用绑定函数。 如果 IrDA 套接字以前使用 绑定绑定到服务名称, 则 connect 函数将失败并SOCKET_ERROR。
- 如果服务名称的格式为“LSAP-SELxxx”,其中 xxx 是范围 1-127 中的十进制整数,则地址指示特定的 LSAP-SEL xxx,而不是服务名称。 此类服务名称允许服务器应用程序接受定向到特定 LSAP-SEL 的传入连接,而无需先执行 ISA 服务名称查询来获取关联的 LSAP-SEL。 此服务名称类型的一个示例是不支持 IAS 的非 Windows 设备。
Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。
Windows 8.1和Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。
示例
以下示例演示如何使用 bind 函数。 有关使用 bind 函数的另一个示例,请参阅使用 Winsock 入门。
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int main()
{
// Declare some variables
WSADATA wsaData;
int iResult = 0; // used to return function results
// the listening socket to be created
SOCKET ListenSocket = INVALID_SOCKET;
// The socket address to be passed to bind
sockaddr_in service;
//----------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"Error at WSAStartup()\n");
return 1;
}
//----------------------
// Create a SOCKET for listening for
// incoming connection requests
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
wprintf(L"socket function failed with error: %u\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(27015);
//----------------------
// Bind the socket.
iResult = bind(ListenSocket, (SOCKADDR *) &service, sizeof (service));
if (iResult == SOCKET_ERROR) {
wprintf(L"bind failed with error %u\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
else
wprintf(L"bind returned success\n");
WSACleanup();
return 0;
}
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows 8.1、Windows Vista [桌面应用 |UWP 应用] |
最低受支持的服务器 | Windows Server 2003 [桌面应用 | UWP 应用] |
目标平台 | Windows |
标头 | winsock.h (包括 Winsock2.h) |
Library | Ws2_32.lib |
DLL | Ws2_32.dll |