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
#include
#include
// 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文档,喵了个咪的。