一些网络开发函数

来源:互联网 发布:宝塔性能优化 编辑:程序博客网 时间:2024/05/29 03:19

几个基础结构体

struct sockaddr {      unsigned short sa_family;         char sa_data[14];     };  struct sockaddr_in {      short int sin_family;         unsigned short int sin_port;         struct in_addr sin_addr;         unsigned char sin_zero[8];     };struct in_addr{      union {        struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;        struct { u_short s_w1,s_w2; } S_un_w;        u_long S_addr;     } S_un;    #define s_addr  S_un.S_addr};  //sockaddr与sockaddr_in之间可以相互转换。in_addr存放的是网络字节序的32位无符号整型IP地址。

几个小端和网络字节序之间的转换函数

//小端转网络字节序u_long htonl(u_long hostlong);u_short htons(u_short hostshort);//网络字节序转小端u_long ntohl(u_long netlong);u_short ntohs(u_long netshort);//其实上面的函数,像htonl也可以用于网络字节序转小端,但为了代码便于阅读,还是养成习惯吧。
//字符串点分十进制 和 网络字节序32位无符号整型 的IP地址的转换函数//旧函数unsigned long inet_addr(  _In_ const char *cp);char* FAR inet_ntoa(//返回的字符串如果要操作最好拷贝到自己的内存中  _In_ struct   in_addr in);//新函数,支持IPv4、IPv6INT WSAAPI InetPton(  _In_  INT    Family,  _In_  PCTSTR pszAddrString,  _Out_ PVOID  pAddrBuf  //in_addr或unsigned long变量的指针);PCTSTR WSAAPI InetNtop(  _In_  INT    Family,  _In_  PVOID  pAddr,  //in_addr或unsigned long变量的指针  _Out_ PTSTR  pStringBuf,  _In_  size_t StringBufSize);

几个名字解析函数

//IP地址和主机名之间的转换函数//旧函数struct hostent* FAR gethostbyname(  _In_ const char *name);/*gethostbyname中操作h_addr_list    hostent *test = gethostbyname("主机名");    char ret[256];    inet_ntop(AF_INET, *++(test->h_addr_list), rer, 256);    MessageBox((rer));*/struct hostent* FAR gethostbyaddr(  _In_ const char *addr,  _In_       int  len,  _In_       int  type);//hostent结构体,返回的hostent由系统管理,不用自己释放typedef struct hostent {  char FAR      *h_name;  char FAR  FAR **h_aliases;  short         h_addrtype;  short         h_length;  char FAR  FAR **h_addr_list;//按网络字节序存储的,要注意} HOSTENT, *PHOSTENT, FAR *LPHOSTENT;//新函数,WS2tcpip.h中int WSAAPI getaddrinfo(  _In_opt_       PCSTR      pNodeName,  _In_opt_       PCSTR      pServiceName,  _In_opt_ const ADDRINFOA  *pHints,  _Out_          PADDRINFOA *ppResult);int WSAAPI getnameinfo(  _In_  const struct sockaddr FAR *sa,  _In_  socklen_t                 salen,  _Out_ char FAR                  *host,  _In_  DWORD                     hostlen,//NI_MAXHOST  _Out_ char FAR                  *serv,  _In_  DWORD                     servlen,//NI_MAXSERV  _In_  int                       flags  //flags有NI_NUMERICSERV、NI_NOFQDN、NI_NUMERICHOST、NI_NAMEREQD、NI_DGRAM);#define NI_MAXSERV    32#define NI_MAXHOST  1025//getaddrinfo和getnameinfo执行成功返回0,执行失败返回非0//获取错误代码比较特别,不是用WSAGetLastError()//而是调用gai_strerror(返回代码)获得错误信息字符串。但官方文档说这个函数是非线程安全的,所以对于各错误代码官网有说明,看需要吧。char* gai_strerror(  _In_ int ecode);//getaddrinfo中的ADDRINFOA声明如下,调用getaddrinfo后返回的ppResult,要调用freeaddrinfo(*ppResult)释放该结构提typedef struct addrinfo {  int             ai_flags;  int             ai_family;  int             ai_socktype;  int             ai_protocol;  size_t          ai_addrlen;  char            *ai_canonname;  struct sockaddr  *ai_addr;  struct addrinfo  *ai_next;} ADDRINFOA, *PADDRINFOA;//释放addrinfo结构体空间void freeaddrinfo(  _In_ struct addrinfo *ai);

提一下getaddrinfo函数调用时参数的填充。
在getaddrinfo函数之前通常需要对以下6个参数进行以下设置:nodename、servname、hints的ai_flags、ai_family、ai_socktype、ai_protocol。
在6项参数中,对函数影响最大的是nodename,sername和 h i n t s . ai_flag,而ai_family只是有地址为v4地址或v6地址的区别。ai_protocol一般是为0不作改动。
getaddrinfo在实际使用中的几种常用参数设置:

参数 取值 值 说明 ai_family AF_INET 2 IPv4 AF_INET6 23 IPv6 AF_UNSPEC 0 协议无关 ai_protocol IPPROTO_IP 0 IP协议 IPPROTO_UDP 17 UDP IPPROTO_TCP 6 TCP ai_socktype SOCK_STREAM 1 流 SOCK_DGRAM 2 数据报 ai_flags AI_PASSIVE 1 被动的,用于bind,通常用于server socket AI_CANONNAME 2 用于返回主机的规范名称 AI_NUMERICHOST 4 地址为数字串
    addrinfo hint,*result;    ZeroMemory(&hint, sizeof(addrinfo));    hint.ai_flags = AI_PASSIVE;    //AI_PASSIVE+空主机+非空端口=通配地址          //无AI_PASSIVE+空主机+非空端口=环回地址    //无论有无AI_PASSIVE+非空主机+无论有无端口=所有地址    hint.ai_family = AF_INET;           hint.ai_protocol = IPPROTO_IP;      int ret = getaddrinfo("主机名", NULL , &hint, &result);    if (ret != 0)    {        MessageBox(gai_strerror(ret));    }    //。。。操作    freeaddrinfo(result);

几个信息获取函数

//获取主机上支持的协议和协议特性int WSAEnumProtocols(  _In_    LPINT              lpiProtocols,  _Out_   LPWSAPROTOCOL_INFO lpProtocolBuffer,  _Inout_ LPDWORD            lpdwBufferLength);//获取协议的状态信息DWORD GetTcpStatistics(  _Out_ PMIB_TCPSTATS pStats);DWORD GetUdpStatistics(  _Out_ PMIB_UDPSTATS pStats);DWORD GetIpStatistics(  _Out_ PMIB_IPSTATS pStats);DWORD GetIcmpStatistics(  _Out_ PMIB_ICMP pStats);//获取活动的TCP或UDPDWORD WINAPI GetTcpTable(  _Out_   PMIB_TCPTABLE pTcpTable,  _Inout_ PDWORD        pdwSize,  _In_    BOOL          bOrder);DWORD GetUdpTable(  _Out_   PMIB_UDPTABLE pUdpTable,  _Inout_ PDWORD        pdwSize,  _In_    BOOL          bOrder);//可以获取本地接口的所有IP地址DWORD GetIpAddrTable(  _Out_   PMIB_IPADDRTABLE pIpAddrTable,  _Inout_ PULONG           pdwSize,  _In_    BOOL             bOrder);//获取网络适配器信息DWORD GetAdaptersInfo(  _Out_   PIP_ADAPTER_INFO pAdapterInfo,  _Inout_ PULONG           pOutBufLen);

其他函数

setsockopt:https://msdn.microsoft.com/en-us/library/windows/desktop/ms740476(v=vs.85).aspx
WSAIoctl:https://msdn.microsoft.com/en-us/library/windows/desktop/ms741621(v=vs.85).aspx

int setsockopt(  _In_       SOCKET s,  _In_       int    level,  _In_       int    optname,  _In_ const char   *optval,  _In_       int    optlen);int WSAIoctl(  _In_  SOCKET                             s,  _In_  DWORD                              dwIoControlCode,  _In_  LPVOID                             lpvInBuffer,  _In_  DWORD                              cbInBuffer,  _Out_ LPVOID                             lpvOutBuffer,  _In_  DWORD                              cbOutBuffer,  _Out_ LPDWORD                            lpcbBytesReturned,  _In_  LPWSAOVERLAPPED                    lpOverlapped,  _In_  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);

SIO_RCVALL:https://msdn.microsoft.com/en-us/library/windows/desktop/ee309610(v=vs.85).aspx

在网络开发过程中还有很多API函数,这只是最近学习到的,整理一波吧。

顺带一提,MFC中ip地址控件的GetAddress方法返回的是小端的32位u_long.

文末贴一下各数据包结构,很有用。

数据包结构体摘自:http://www.cnblogs.com/RodYang/p/3271878.html

//以太帧头格式结构体,共14个字节:  typedef struct ether_header {   unsigned char ether_dhost[6];   //目的MAC地址   unsigned char ether_shost[6];   //源MAC地址   unsigned short ether_type;     //协议类型  }ETHHEADER,*PETHHEADER;//IPv4报头格式结构体,共20个字节:    typedef struct ipv4_header {unsigned char ver_ihl;          //版本 (4 bits) + 首部长度 (4 bits)unsigned char tos;             //服务类型unsigned short tlen;            //数据报总长度unsigned short identification;    //标识unsigned short flags_fo;        //标志 (3 bits) + 片偏移 (13 bits)        unsigned char ttl;             //生存时间unsigned char proto;           //协议unsigned short crc;            //首部校验和u_char ip_src[4];              //源IP地址u_char ip_dst[4];              //目的IP地址    }IPHEADER,*PIPHEADER;//IPv6报头格式结构体,共40个字节:typedef struct ipv6_header {u_char ver_tf;                //版本号(4 bit)u_char traffic;                //优先级(8 bit)u_short label;                //流标识(20 bit)u_char length[2];             //报文长度(16 bit)u_char next_header;           //下一头部(8 bit)u_char limits;                //跳数限制(8 bit)u_char Srcv6[16];            //源IPv6地址(128 bit)u_char Destv6[16];           //目的IPv6地址(128 bit)}IPv6_HEADER,*PIPv6_HEADER;//TCP报头格式结构体,共20个字节:typedef struct tcp_header {WORD SourPort;       //源端口号  WORD DestPort;       //目的端口号DWORD SeqNo;       //序号DWORD AckNo;       //确认序号BYTE HLen;          //首部长度(保留位)BYTE Flag;           //标识(保留位)WORD Window;       //窗口大小WORD ChkSum;       //校验和WORD UrgPtr;        //紧急指针}TCPHEADER,*PTCPHEADER;//UDP报头格式结构体,共8个字节:typedef struct udp_header {u_short sport;          //源端口号u_short dport;          //目的端口号u_short len;            //数据报长度u_short crc;            //校验和}UDPHEADER,*PUDPHEADER;
0 0
原创粉丝点击