网络编程Winsock——bind

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];
};

IPv6用这个:

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) );

在MSDN上有这么一段话“The SOCKADDR_STORAGE structure also stores socket address information and the structure is sufficiently large to store IPv4 or IPv6 address information. The use of the SOCKADDR_STORAGE structure promotes protocol-family and protocol-version independence, and simplifies development. It is recommended that the SOCKADDR_STORAGE structure be used in place of the sockaddr structure. The SOCKADDR_STORAGE structure is supported on Windows Server 2003 and later.”

大概的意思是说SOCKADDR_STORAGE这个东西好啊,大家用这个吧,然后没有给出更多的解释也没有相关代码,让自己去看RFC 2553文档,喵了个咪的。






你可能感兴趣的:(bind,网络编程,winsock,Sockets)