《Windows API巡礼》---socket和bind

来源:互联网 发布:被明星搭讪 知乎 编辑:程序博客网 时间:2024/05/19 22:04

函数socket()可以创建一个socket对象:

SOCKET WSAAPI socket(

  __in  int af, //协议的地址家族,在Windows操作系统中,取值只能是AF_INET

               //表示该套接字在Internet域中进行通信

  __in  int type, //套接字类型,当af=AF_INET时只有3种取值:

                   //SOCK_STREAM---TCP,数据被看作字节流,无长度限制

                   //SOCK_DGRAM---UDP,数据包以独立包形式发送

                   //SOCK_RAW---Raw sockets,允许对较低层协议如IPICMP直接访问

  __in  int protocol //指定网络协议:IPPROTO_IPIPPROTO_UDPIPPROTO_RAW

);

返回值:

成功时,返回一个创建好的套接字;

失败时,返回INVALID_SOCKET,可调用WSAGetLastError()函数查看错误信息。

socket函数使用实例如下:

#ifndef UNICODE

#define UNICODE 1

#endif

 

// link with Ws2_32.lib

#pragma comment(lib,"Ws2_32.lib")

 

#include <winsock2.h>

#include <ws2tcpip.h>

#include <stdio.h>

#include <stdlib.h>   // Needed for _wtoi

 

 

int __cdecl wmain(int argc, wchar_t **argv)

{

 

    //-----------------------------------------

    // Declare and initialize variables

    WSADATA wsaData = {0};

    int iResult = 0;

 

//    int i = 1;

 

    SOCKET sock = INVALID_SOCKET;

    int iFamily = AF_UNSPEC;

    int iType = 0;

    int iProtocol = 0;

 

    // Validate the parameters

    if (argc != 4) {

        wprintf(L"usage: %s <addressfamily> <type> <protocol>/n", argv[0]);

        wprintf(L"socket opens a socket for the specified family, type, & protocol/n");

        wprintf(L"%ws example usage/n", argv[0]);

        wprintf(L"   %ws 0 2 17/n", argv[0]);

        wprintf(L"   where AF_UNSPEC=0 SOCK_DGRAM=2 IPPROTO_UDP=17/n", argv[0]);

        return 1;

    }

 

    iFamily = _wtoi(argv[1]);

    iType = _wtoi(argv[2]);

    iProtocol = _wtoi(argv[3]);

   

    // Initialize Winsock

    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);

    if (iResult != 0) {

        wprintf(L"WSAStartup failed: %d/n", iResult);

        return 1;

    }

 

    wprintf(L"Calling socket with following parameters:/n");

    wprintf(L"  Address Family = ");

    switch (iFamily) {

    case AF_UNSPEC:

        wprintf(L"Unspecified");

        break;

    case AF_INET:

        wprintf(L"AF_INET (IPv4)");

        break;

    case AF_INET6:

        wprintf(L"AF_INET6 (IPv6)");

        break;

    case AF_NETBIOS:

        wprintf(L"AF_NETBIOS (NetBIOS)");

        break;

    case AF_BTH:

        wprintf(L"AF_BTH (Bluetooth)");

        break;

    default:

        wprintf(L"Other");

        break;

    }

    wprintf(L" (%d)/n", iFamily);

   

    wprintf(L"  Socket type = ");

    switch (iType) {

    case 0:

        wprintf(L"Unspecified");

        break;

    case SOCK_STREAM:

        wprintf(L"SOCK_STREAM (stream)");

        break;

    case SOCK_DGRAM:

        wprintf(L"SOCK_DGRAM (datagram)");

        break;

    case SOCK_RAW:

        wprintf(L"SOCK_RAW (raw)");

        break;

    case SOCK_RDM:

        wprintf(L"SOCK_RDM (reliable message datagram)");

        break;

    case SOCK_SEQPACKET:

        wprintf(L"SOCK_SEQPACKET (pseudo-stream packet)");

        break;

    default:

        wprintf(L"Other");

        break;

    }

    wprintf(L" (%d)/n", iType);

 

    wprintf(L"  Protocol = %d = ", iProtocol);

    switch (iProtocol) {

    case 0:

        wprintf(L"Unspecified");

        break;

    case IPPROTO_ICMP:

        wprintf(L"IPPROTO_ICMP (ICMP)");

        break;

    case IPPROTO_IGMP:

        wprintf(L"IPPROTO_IGMP (IGMP)");

        break;

    case IPPROTO_TCP:

        wprintf(L"IPPROTO_TCP (TCP)");

        break;

    case IPPROTO_UDP:

        wprintf(L"IPPROTO_UDP (UDP)");

        break;

    case IPPROTO_ICMPV6:

        wprintf(L"IPPROTO_ICMPV6 (ICMP Version 6)");

        break;

    default:

        wprintf(L"Other");

        break;

    }

    wprintf(L" (%d)/n", iProtocol);

 

    sock = socket(iFamily, iType, iProtocol);

    if (sock == INVALID_SOCKET)

        wprintf(L"socket function failed with error = %d/n", WSAGetLastError() );

    else

        wprintf(L"socket function succeeded/n", WSAGetLastError() );

 

    WSACleanup();

 

    return 0;

}

 

 

函数bind用来将本地地址附加到所创建的套接字上以便能够有效地标识套接字:

int bind(

  __in  SOCKET s, //标识未绑定套接字的句柄

  __in  const struct sockaddr *name, //用来赋予套接字地址,一般用struct sockaddr_in结构表示

  __in  int namelen //name指向的值的字节大小

);

返回值:

成功时,返回0

失败时,返回SOCKET_ERROR,调用WSAGetLastError函数查看进一步错误信息。

其中:

struct sockaddr {

        ushort  sa_family; //地址家族,一般为AF_INET

        char    sa_data[14]; //14字节的IP地址

};

 

struct sockaddr_in {

        short   sin_family; //Windows下为AF_INET,表示该socket位于Internet

        u_short sin_port; //指定服务端口

        struct  in_addr sin_addr; //用于保存IP地址

        char    sin_zero[8]; //只起填充作用

};

 

bind函数使用实例如下:

#include <stdio.h>

#include "winsock2.h"

#include <windows.h>

#pragma comment(lib, "wininet.lib")

 

void main() {

  //----------------------

  // Initialize Winsock

  WSADATA wsaData;

  int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

  if (iResult != NO_ERROR)

    printf("Error at WSAStartup()/n");

 

  //----------------------

  // Create a SOCKET for listening for

  // incoming connection requests

  SOCKET ListenSocket;

  ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if (ListenSocket == INVALID_SOCKET) {

    printf("Error at socket(): %ld/n", WSAGetLastError());

    WSACleanup();

    return;

  }

  //----------------------

  // The sockaddr_in structure specifies the address family,

  // IP address, and port for the socket that is being bound.

  sockaddr_in service;

  service.sin_family = AF_INET;

  service.sin_addr.s_addr = inet_addr("127.0.0.1");

  service.sin_port = htons(27015);

 

  //----------------------

  // Bind the socket.

  if (bind( ListenSocket,

    (SOCKADDR*) &service,

    sizeof(service)) == SOCKET_ERROR) {

    printf("bind() failed./n");

    closesocket(ListenSocket);

    return;

  }

 

  WSACleanup();

  return;

}

 

 

shutdown函数用来中断socket连接,通知接收端或发送端“停止接收数据”或“停止发送数据”:

int shutdown(

  __in  SOCKET s, //指定要中断的套接字连接

  __in  int how //指定关闭的方式:SD_RECEIVE(禁止接收)SD_SEND(禁止发送)

//SD_BOTH(同时禁止接收和发送)

);

返回值:

成功时,返回0

失败时,返回SOCKET_ERROR,调用WSAGetLastError函数查看进一步错误信息。

 

closesocket函数用来关闭套接字:

int closesocket(

  __in  SOCKET s //指定要关闭的套接字

);

返回值:

成功时,返回0

失败时,返回SOCKET_ERROR,调用WSAGetLastError函数查看进一步错误信息。

原创粉丝点击