zoukankan      html  css  js  c++  java
  • Windows网络编程笔记4 -- Winsock 协议相关知识

           Win32平台上的Winsock编程,Winsock是一个与协议无关的接口。以下协议是我们需要了解的:

    网络协议的特征包括:

      1、  面向消息

      2、  面向连接和无线接

      3、  可靠性和次序性

      4、  从容关闭(这是指协议中断,连接不会立即中断)

      5、  广播数据

      6、  多播数据

      7、  服务质量(QOS)

      8、  部分消息(大数据进行分段发送,分段接受)

      9、  路由选择(考虑协议是否可路由)

      10、  字节序

      11、  最大传输单元

    Windows支持的协议如下图

    Winsocket协议相关结构介绍

    //获得系统中安装的网络协议的相关信息
    int WSAEnumProtocols(
      _In_     LPINT lpiProtocols,//
      _Out_    LPWSAPROTOCOL_INFO lpProtocolBuffer,//
      _Inout_  LPDWORD lpdwBufferLength//
    );

    其中的相关信息都保存在参数二当中,这个一个数据结构

     1 //本机协议信息
     2 typedef struct _WSAPROTOCOL_INFO {
     3   DWORD            dwServiceFlags1;//协议标志
     4   DWORD            dwServiceFlags2;//
     5   DWORD            dwServiceFlags3;//
     6   DWORD            dwServiceFlags4;//
     7   DWORD            dwProviderFlags;//
     8   GUID             ProviderId;//
     9   DWORD            dwCatalogEntryId;//
    10   WSAPROTOCOLCHAIN ProtocolChain;//
    11   int              iVersion;//
    12   int              iAddressFamily;//
    13   int              iMaxSockAddr;//
    14   int              iMinSockAddr;//
    15   int              iSocketType;//
    16   int              iProtocol;//
    17   int              iProtocolMaxOffset;//
    18   int              iNetworkByteOrder;//
    19   int              iSecurityScheme;//
    20   DWORD            dwMessageSize;//
    21   DWORD            dwProviderReserved;//
    22   TCHAR            szProtocol[WSAPROTOCOL_LEN+1];//
    23 } WSAPROTOCOL_INFO, *LPWSAPROTOCOL_INFO;//

    而其中比较重要的参数是dwServiceFlags1,如下图

    如何打开Socket

      在可以调用一个Winsock函数之前,必须先加载一个版本正确的Winsock库。Winsock启动例程是WSAStartip();

          第一个参数是准备加载的Winsock库的版本号。就目前的 Win32平台而言,Winsock2库的最新版本是 2.2。唯一的例外是 Windows CE,它只支持 Winsock1.1版。如果需要Winsock2.2版,指定这个值(0x0202)或使用宏MAKEWORD(2,2)即可。高位字节指定副版本,而低位字节则指定主版本。

      第二个参数是 WSADATA结构,它是调用完成之后立即返回的。

      接着使用Winsocket函数

      最后清除,记住,每次调用WSACleanup,都需要调用相应的 WSACleanup,因为每次启动调用都会增加对加载 Winsock DLL的引用次数,它要求调用同样多次的 WSACleanup,以此抵消引用次数。

     1 // WSAData数据结构
     2 typedef struct WSAData {
     3   WORD           wVersion;//Winsock版本号
     4   WORD           wHighVersion;//最高版本号
     5   char           szDescription[WSADESCRIPTION_LEN+1];//Winsock说明
     6   char           szSystemStatus[WSASYS_STATUS_LEN+1];//系统状态信息
     7   unsigned short iMaxSockets;//套接字的最大编号
     8   unsigned short iMaxUdpDg;//UDP数据报的最大容量
     9   char FAR       *lpVendorInfo;//厂商专有信息
    10 } WSADATA, *LPWSADATA;
    //1.启用socket库,初始化
        WSAData wsa;
        if (0 != WSAStartup(MAKEWORD(2,0),&wsa))
        {
            cout<<"Socket2.0初始化失败,Exit!"<<endl;
            return ;
        }
    //2.创建套接字
    ......
    //3.绑定套接字
    .....
    //4.监听
    ......
    //5.连接
    .....
    //6.通信
    ....
    //7.断开
    ....
    //8.清除
    if (!WSACleanup())
        {
            WSAGetLastError();
            return;
        }

    SOCKET 的使用有两种定义方式

    //方法1
    SOCKET WSASocket(
      _In_  int af,
      _In_  int type,
      _In_  int protocol,
      _In_  LPWSAPROTOCOL_INFO lpProtocolInfo,//0表示默认的协议条目
      _In_  GROUP g,//组参数始终为0
      _In_  DWORD dwFlags //
    );
    //方法2 SOCKET WSAAPI socket( _In_ int af,//地址家族 _In_ int type,//套接字类型 _In_ int protocol//协议字段 );

    类型参考如

      在类型里可以看到一个不常用的套接字,原始套接字。

    原始套接字

      raw socket,即原始套接字,可以接收本机网卡上的数据帧或者数据包,对与监听网络的流量和分析是很有作用的。

      原始套接字一种通信,允许你把其他协议封装在 U D P数据包中,比如说“互联网控制消息协议”(I C M P)。I C M P的目的是投递互联网主机间的控制、错误和信息型消息。由于 I C M P不提供任何数据传输功能,因此不能把它与 U D P或T C P同等看待,但它和 I P本身属于同一个级别。

    创建套接字常用的结构如下

    struct sockaddr {
            ushort  sa_family;//地址家族啊
            char    sa_data[14];//不同网络地址结构的大小
    };
    
    struct sockaddr_in{
       short sin_family;//地址家族
       unsigned short sin_port;//IP端口
       struct in_addr sin_addr;//IP地址
       char sin_zero[8];//填充结构,使其余SOCKETADDR的大小一致
    };

    还有一点需要注意在网络中传输的数据的顺序是网络字节顺序,和主机字节顺序不同,以下是几个相互转换的函数:

    //将一个ip地址转换成一个32位无符号长整数。
    unsigned long inet_addr(
      _In_  const char *cp
    );
    //将主机字节顺序转换成网络字节顺序
    u_long WSAAPI htonl(
      _In_  u_long hostlong
    );
    //将主机字节顺序转换成16位网络字节顺序返回
    u_short WSAAPI htons(
      _In_  u_short hostshort
    );
    一下两个刚好相反:
    //将16位网络字节顺序转换成主机字节顺序返回
    u_short WSAAPI ntohs(
      _In_  u_short netshort
    );
    //将网络字节顺序转换成主机字节顺序
    u_long WSAAPI ntohl(
      _In_  u_long netlong
    );

    名字解析

       通过已知信息获取网络信息

    //通过主机名获得主机的相关信息,返回值为hostent结构指针
    struct hostent* FAR gethostbyname(
      _In_  const char *name
    );
    
    
    //通过主机名获得主机ip地址的相关信息,返回值为hostent结构指针
    struct hostent* FAR gethostbyaddr(
      _In_  const char *addr,
      _In_  int len,
      _In_  int type
    );
    
    //hostent结构
    typedef struct hostent {
      char FAR      *h_name;//正式主机名
      char FAR  FAR **h_aliases;//主机的别名
      short         h_addrtype;//ip地址类型
      short         h_length;//IP地址长度
      char FAR  FAR **h_addr_list;//主机的IP地址(网络字节顺序)
    } HOSTENT, *PHOSTENT, FAR *LPHOSTENT;
    
    //获得已知服务的端口号
    struct servent* FAR getservbyname(
      _In_  const char *name,//服务名
      _In_  const char *proto//随便指向一个字串,这个字串表明name中的服务是在这个参数中的协议下面注册的。
    );

       

  • 相关阅读:
    团队第二阶段冲刺——第三天
    团队第二阶段冲刺——第二天
    团队第二阶段冲刺——第一天
    第一阶段意见汇总
    团队第一次绩效考核
    我们与同类产品的差距
    团队项目第一阶段成果评价
    第一阶段验收成果总结
    团队冲刺第十天
    团队冲刺第九天
  • 原文地址:https://www.cnblogs.com/songliquan/p/3407084.html
Copyright © 2011-2022 走看看