bind 绑定套接字,成功返回0,错误可以调用WSAGetLastError。
int bind( _In_ SOCKET s,//一个尚未绑定的套接字 _In_ const struct sockaddr *name,//绑定到套接字的地址 _In_ int namelen//参数二的字节长度 );
MSDN上的一段话表明了为什么要有这么一个绑定操作。“When a socket is created with a call to the socket function, it exists in a namespace (address family), but it has no name assigned to it. Use the bind function to establish the local association of the socket by assigning a local name to an unnamed socket.”
意思是说曾经有个人英语不好,后来没有后来了。
关于参数二:
在生成地址时,MSDN提到了一句话“Binding to a specific port number other than port 0 is discouraged for client applications, since there is a danger of conflicting with another socket already using that port number on the local computer.”
意思是说最好使用0来作为端口数,用别的可能会因为已经被占用而导致冲突。(当然自己指定也是可以的。)好多课本教材什么的没有提及这一点。
下面是MSDN上的示例代码(http://msdn.microsoft.com/en-us/library/windows/desktop/ms737550%28v=vs.85%29.aspx)
#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; }
对于这一句
service.sin_addr.s_addr = inet_addr("127.0.0.1");s_addr是一个宏定义
#define s_addr S_un.S_addr
关于参数二的合成,MSDN上有专门的一项讲述了sockaddr(http://msdn.microsoft.com/en-us/library/windows/desktop/ms740496%28v=vs.85%29.aspx)
IPv4用这个:
struct sockaddr { ushort sa_family; char sa_data[14]; }; struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; };
struct sockaddr_in6 { short sin6_family; u_short sin6_port; u_long sin6_flowinfo; struct in6_addr sin6_addr; u_long sin6_scope_id; }; typedef struct sockaddr_in6 SOCKADDR_IN6; typedef struct sockaddr_in6 *PSOCKADDR_IN6; typedef struct sockaddr_in6 FAR *LPSOCKADDR_IN6; struct sockaddr_in6_old { short sin6_family; u_short sin6_port; u_long sin6_flowinfo; struct in6_addr sin6_addr; };这段代码也讲述了怎样生成参数二:
// Declare variables SOCKET ListenSocket; struct sockaddr_in saServer; hostent* localHost; char* localIP; // Create a listening socket ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Get the local host information localHost = gethostbyname(""); localIP = inet_ntoa (*(struct in_addr *)*localHost->h_addr_list); // Set up the sockaddr structure saServer.sin_family = AF_INET; saServer.sin_addr.s_addr = inet_addr(localIP); saServer.sin_port = htons(5150); // Bind the listening socket using the // information in the sockaddr structure bind( ListenSocket,(SOCKADDR*) &saServer, sizeof(saServer) );
大概的意思是说SOCKADDR_STORAGE这个东西好啊,大家用这个吧,然后没有给出更多的解释也没有相关代码,让自己去看RFC 2553文档,喵了个咪的。