bind 函数 (winsock2.h)
绑定 函数将本地地址与套接字相关联。
语法
int WSAAPI bind(
[in] SOCKET s,
[in] const sockaddr *name,
[in] int namelen
);
参数
[in] s
标识未绑定套接字的描述符。
[in] name
指向要分配给绑定套接字的本地地址的 sockaddr 结构的指针。
[in] namelen
名称 参数指向的值的长度(以字节为单位)。
返回值
如果未发生错误,绑定 返回零。 否则,它返回SOCKET_ERROR,可以通过调用 WSAGetLastError来检索特定的错误代码。
错误代码 | 意义 |
---|---|
注意 在使用此函数之前,必须进行成功的 WSAStartup 调用。
|
|
网络子系统已失败。 | |
尝试以禁止其访问权限的方式访问套接字。
如果尝试将数据报套接字绑定到广播地址失败,则返回此错误,因为未启用 setsockopt 选项SO_BROADCAST。 |
|
通常只允许使用每个套接字地址(协议/网络地址/端口)。
如果计算机上的进程已绑定到同一完全限定的地址,并且套接字尚未标记为允许使用SO_REUSEADDR重复使用地址,则返回此错误。 例如,名称 参数中指定的 IP 地址和端口已绑定到另一个应用程序正在使用的另一个套接字。 有关详细信息,请参阅 SOL_SOCKET 套接字选项 参考中的SO_REUSEADDR套接字选项,使用SO_REUSEADDR和SO_EXCLUSIVEADDRUSE,以及 SO_EXCLUSIVEADDRUSE。 |
|
请求的地址在其上下文中无效。
如果 名称 参数指向的指定地址在此计算机上不是有效的本地 IP 地址,则返回此错误。 |
|
系统在尝试在调用中使用指针参数时检测到无效的指针地址。
如果 名称 参数为 NULL,则返回此错误。 名称 或 namelen 参数不是用户地址空间的有效部分,namelen 参数太小,名称 参数包含关联的地址系列不正确的地址格式,或者由 名称指定的内存块的前两个字节 与关联的地址系列不匹配具有套接字描述符 s。 |
|
正在阻止 Windows 套接字 1.1 调用,或者服务提供商仍在处理回调函数。 | |
提供了无效的参数。
此错误返回套接字 已绑定到地址。 |
|
无法对套接字执行操作,因为系统缺少足够的缓冲区空间或队列已满。
此错误返回的缓冲区不足或连接过多。 |
|
尝试对不是套接字的内容执行操作。
如果 s 参数中的描述符不是套接字,则返回此错误。 |
言论
在后续调用 侦听 函数之前,需要在未连接的套接字上 绑定 函数。 它通常用于绑定到面向连接的(流)或无连接(数据报)套接字。 绑定 函数还可用于绑定到原始套接字(该套接字是通过调用 套接字 函数创建的,并将 类型 参数设置为SOCK_RAW)。 在后续调用 connect、ConnectEx、WSAConnect、WSAConnectByList或 WSAConnectByName 函数之前,还可以在未连接的套接字上使用 绑定 函数。
使用对 套接字 函数的调用创建套接字时,该套接字存在于命名空间(地址系列),但它没有为其分配名称。 使用 绑定 函数通过将本地名称分配给未命名套接字来建立套接字的本地关联。
使用 Internet 地址系列时,名称由三个部分组成:
- 地址系列。
- 主机地址。
- 标识应用程序的端口号。
在 Windows 套接字 2 中,名称 参数不严格解释为指向 sockaddr 结构的指针。 它以这种方式强制转换为 Windows 套接字 1.1 兼容性。 服务提供商可以将其视为指向大小块 名称的内存块的指针。 此块中的前 2 个字节(对应于 sockaddr 结构的 sa_family 成员、sockaddr_in 结构的 sin_family 成员或 sockaddr_in6 结构的 sin6_family 成员)必须包含用于创建套接字的地址系列。 否则,会发生错误 WSAEFAULT。
如果应用程序不关心分配的本地地址,请在 名称 参数的 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 设置不同。 有关详细信息,请参阅 KB 929851。
应用程序可以在调用 绑定 后使用 getsockname 来了解分配给套接字的地址和端口。 如果 Internet 地址等于 INADDR_ANY 或 in6addr_any,则 getsockname 在连接套接字之前不能提供地址,因为如果主机是多宿主的,则多个地址可能有效。 对于客户端应用程序,不建议绑定到除端口 0 以外的特定端口号,因为存在在本地计算机上已使用该端口号的另一个套接字发生冲突的危险。
对于多播操作,首选方法是调用 绑定 函数,将套接字与本地 IP 地址相关联,然后加入多播组。 尽管此操作顺序不是强制性的,但强烈建议这样做。 因此,多播应用程序将首先在本地计算机上选择 IPv4 或 IPv6 地址、通配符 IPv4 地址(INADDR_ANY),或通配符 IPv6 地址(in6addr_any)。 然后,多播应用程序将调用 绑定 函数,并在 名称 参数 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 客户端套接字在 连接 函数之前,绝不能调用 绑定 函数。 如果 IrDA 套接字以前使用 绑定绑定到服务名称,则 连接 函数将失败并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 应用商店应用支持此函数。
例子
以下示例演示如何使用 绑定 函数。 有关使用 绑定 函数的另一个示例,请参阅 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 应用] |
目标平台 | 窗户 |
标头 | winsock2.h (包括 Winsock2.h) |
库 | Ws2_32.lib |
DLL | Ws2_32.dll |
另请参阅
使用SO_REUSEADDR和SO_EXCLUSIVEADDRUSE