一、不带参宏定义


WORD

函数源码

  1. // 宏定义
  2. typedef unsigned short WORD; // 相当于是一个无符号短整型变量

使用示例:
配合定义MAKEWORD()使用

  1. WORD myWordVersion = MAKEWORD(2, 2); // MAKEWORD(2,2) 参数用于在系统上请求 Winsock 2.2 版本
  2. // 前面2是高字节记录,后面2是低字节记录

二、结构体(带参宏定义)


1.WSADATA structure

源码:

  1. typedef struct WSAData {
  2. WORD wVersion;
  3. WORD wHighVersion;
  4. #if ...
  5. unsigned short iMaxSockets;
  6. #if ...
  7. unsigned short iMaxUdpDg;
  8. #if ...
  9. char *lpVendorInfo;
  10. #if ...
  11. char szDescription[WSADESCRIPTION_LEN + 1];
  12. #if ...
  13. char szSystemStatus[WSASYS_STATUS_LEN + 1];
  14. #else
  15. char szDescription[WSADESCRIPTION_LEN + 1];
  16. #endif
  17. #else
  18. char szSystemStatus[WSASYS_STATUS_LEN + 1];
  19. #endif
  20. #else
  21. unsigned short iMaxSockets;
  22. #endif
  23. #else
  24. unsigned short iMaxUdpDg;
  25. #endif
  26. #else
  27. char *lpVendorInfo;
  28. #endif
  29. } WSADATA;

功能:
用于存储被WSAStartup函数调用后返回的 Windows Sockets数据。它包含Winsock.dll执行的数据。

2. HOSTENT structure

源码:

  1. typedef struct hostent {
  2. char *h_name;
  3. char **h_aliases;
  4. short h_addrtype;
  5. short h_length; //主机IP地址字节长度,对于IPv4是四字节,即32位
  6. char **h_addr_list;
  7. } HOSTENT, *PHOSTENT, *LPHOSTENT;

结构体成员变量:

  1. - h_name
  2. - 主机 (PC) 的正式名称。如果使用 DNS 或类似的解析系统,则是完全限定域名 (FQDN) 导致服务器返回回复。如果使用本地主机文件,则它是 IPv4 地址之后的第一个条目。
  3. - h_aliases
  4. - 以**NULL**结尾的备用名称数组。
  5. - h_addrtype
  6. - 返回IP地址类型
  7. - h_length
  8. - 每个地址的长度
  9. - h_addr_list
  10. - 以**NULL**结尾的主机地址列表。地址以网络字节顺序返回。
  11. - ⭐兄台兄台,前方高能🚨:注意**h_addr_list**的返回存储格式是网络字节顺序。千万不要直接用printf带%s参数来打这个东西,会有问题的哈。所以到真正需要打印出这个IP的话,需要调用**inet_addr()或inet_ntoa()**。

简要描述:
配合gethostbyaddr 和 gethostbyname函数使用,gethostbyaddr 和 gethostbyname 函数返回一个hostent的指针,该结构是由 Windows 套接字分配的结构。hostent 结构包含成功搜索 name 参数中指定的主机的结果。

3.SOCKADDR_IN structure

源码:

  1. typedef struct sockaddr_in {
  2. #if(_WIN32_WINNT < 0x0600)
  3. short sin_family;
  4. #else //(_WIN32_WINNT < 0x0600)
  5. ADDRESS_FAMILY sin_family;
  6. #endif //(_WIN32_WINNT < 0x0600)
  7. USHORT sin_port;
  8. IN_ADDR sin_addr;
  9. CHAR sin_zero[8];
  10. } SOCKADDR_IN, *PSOCKADDR_IN;

结构体成员变量:

  1. - **sin_family:**
  2. - 传输地址的地址族。此成员应始终设置为 AF_INET
  3. - **sin_port:**
  4. - 传输协议端口号。
  5. - **sin_addr:**
  6. - 包含 IPv4 传输地址的 [IN_ADDR](https://docs.microsoft.com/en-us/previous-versions/windows/hardware/drivers/ff556972(v=vs.85)) 结构。
  7. - **sin_zero[8]:**
  8. - 保留供系统使用。WSK 应用程序应将此数组的内容设置为零。

高能注意:
⭐除地址族外,SOCKADDR_IN 结构中的所有数据都必须以网络字节顺序(大端)指定。
简要描述:
SOCKADDR_IN 结构体为 AF_INET 地址族指定传输地址和端口

二、部分API函数


1.WSAStartup( )——进行相应的socket库绑定

简要描述:
初始化 Windows Sockets DLL,该函数是网络程序中最先使用的Windows Socke 函数,其它函数都要在WSA Startup调用成功之后才能正常运行。
源码:

  1. int WSAStartup(
  2. WORD wVersionRequired,
  3. LPWSADATA lpWSAData
  4. );

函数参数:

  1. - ***wVersionRequested:**Windows Sockets API提供的调用方可使用的最高版本号。高位字节指出副版本(修正)号,低位字节指明主版本号。
  2. - ***lpWSAData:**指向WSADATA数据结构的指针,用于接收 Windows Sockets 实现的详细信息。

函数返回值:
如果函数WSAStartup()执行成功,返回0;否则返回相应的错误代码。

2.WSACleanup( )

简要描述:
完成Windows Sockets 的使用之后,应用程序或DLL必须调用WSACleanup()将其从Windows Sockets的实现中注销,实现资源的释放。(与WSAStartup成对出现
源码:

  1. int WSACleanup();

函数返回值:
如果操作成功,则返回值为零。否则,返回值 SOCKET_ERROR,并且可以通过调用WSAGetLastError检索特定的错误编号 。

3.WSAGetLastError( )

简要描述:
获得上次操作失败的错误号。
源码:

  1. int WSAAPI WSAGetLastError();

返回值:
返回值指示此线程上次失败的 Windows 套接字操作的错误代码。

4.gethostname( )

简要描述:
从本地获取标准券的主机名。
源码:

  1. #define WSAAPI FAR PASCAL
  2. int WSAAPI gethostname(
  3. _Out_writes_bytes_(namelen) char FAR * name,
  4. _In_ int namelen
  5. );

参数:

  1. - ***name:**指向接收本地主机名的缓冲区的**指针**。 👉 _引用传递_
  2. - ***namelen:**指向的缓冲区的**长度**(以字节为单位)。

返回值:
如果没有发生错误,gethostname返回零。否则,它返回 SOCKET_ERROR 并且可以通过调用WSAGetLastError检索特定的错误代码(错误代码可以通过WSAGetLastError()函数获得) 。

5.gethostbyname( )

简要描述:
通过主机名获得主机信息。(👉主机名通过gethostname( )函数获得)
源码:

  1. #include <netdb.h>
  2. extern int h_errno;
  3. struct hostent {
  4. char *h_name; /* 查询主机的规范名字 */
  5. char **h_aliases; /* 别名 */
  6. int h_addrtype; /* AF_INET */
  7. int h_length; /* 4 */
  8. char **h_addr_list; /* IPv4地址 */
  9. }
  10. struct hostent *gethostbyname(const char *name);

参数:

  1. - ***name:**传入由[gethostname( )](#quQv9)函数获得的结果,或者自己设置输入主机名OR域名。

返回值:
gethostbyname将返回一个指向上述hostent结构的指针 。如果发生错误,它会返回一个空指针,并且可以通过调用WSAGetLastError来检索特定的错误编号。
示例代码:

  1. #include <iostream>
  2. #include <WinSock2.h>
  3. #pragma comment(lib,"ws2_32.lib")
  4. using namespace std;
  5. int main() {
  6. WORD myWordVersion = MAKEWORD(2,2); // WORD ——> typedef unsigned short WORD; 相当于是一个无符号短整型变量
  7. // 创建的 WinSocket 版本 2.2
  8. WSADATA wsaData;
  9. char hostname[255];
  10. int startErr; // 函数调用错误返回值检测
  11. WSAStartup(myWordVersion, &wsaData);
  12. LPHOSTENT pHost;
  13. SOCKADDR_IN addrInfos;
  14. gethostname(hostname,sizeof(hostname));
  15. pHost = gethostbyname(hostname);
  16. printf("主机名:%s\n",pHost->h_name);
  17. printf("IP地址类型:%d\n", pHost->h_addrtype);
  18. printf("地址长度:%d\n", pHost->h_length);
  19. for (int n = 0; pHost->h_addr_list[n]; n++) {
  20. memcpy(&addrInfos.sin_addr, pHost->h_addr_list[n], pHost->h_length); // 将pHost结构体指针中的h_addr_list依次拷贝到
  21. // 标准的ip地址标准结构体SOCKADDR_IN中方便后续函数的处理
  22. cout << inet_ntoa(addrInfos.sin_addr) << endl;
  23. }
  24. WSACleanup();
  25. return 0;
  26. }

6.gethostbyaddr( )

简要描述:
根据网络地址获取主机信息
源码:

  1. hostent *WSAAPI gethostbyaddr(
  2. const char *addr,
  3. int len,
  4. int type
  5. );

参数:

  1. - ***addr:**所学要解析的地址
  2. - ***len:**IPV4 地址长度为4个字节
  3. - ***type:**地址类型为 AF_INET

返回值:
gethostbyaddr 会返回一个指向hostent结构的指针 。如果执行错误,它返回一个空指针,并且可以通过调用WSAGetLastError来检索特定的错误代码 。

7.memset( )

简要描述:

源码:

  1. void *memset(
  2. void *dest,
  3. int c,
  4. size_t count // size_t 是无符号整数类型
  5. );

参数:

  1. - ***dest:**指向要填充的字符串
  2. - ***c:**要设置的值。该值以int类型传递,但该函数使用该值的无符号字符转换来填充内存块。
  3. - ***count:**要设置为值的字节数。size_t 是无符号整数类型。(配合sizeof函数使用)

8.memcpy( )

简要描述:
复制内存块
源码:

  1. void *memcpy(
  2. void *dest,
  3. const void *src,
  4. size_t count // size_t 是无符号整数类型
  5. );

参数:

  1. - *dest:指向要复制内容的目标数组的**指针**,类型转换为void*类型的指针。
  2. - *src:指向要复制的数据源的**指针**,类型转换为const void*类型的指针。
  3. - *count:要复制的字节数。(配合sizeof函数使用)

补:⭐strcpy和memcpy的区别
strcpy和memcpy都是标准C库函数。

  1. - **复制的内容不同**。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
  2. - **复制的方法不同**。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。_memcpy则是根据其第3个参数决定复制的长度。_
  3. - **用途不同**。通常在复制字符串时用strcpy,而需要复制其他类型数据时一般用memcpy

9.getprotobyname( )

简要描述:
检索对应于协议名称的协议信息。
源码:

  1. typedef struct protoent {
  2. char *p_name; // 协议的正式名称。如:TCP、UDP……
  3. char **p_aliases; // 以空字符结尾的备用名称数组。
  4. short p_proto; // 协议编号,以主机字节顺序排列。
  5. } PROTOENT, *PPROTOENT, *LPPROTOENT;
  6. // 该protoent结构包含名称和协议号对应于一个给定的协议名称。
  7. // 应用程序绝不能尝试修改此结构或释放其任何组件。此外,每个线程仅分配此结构的一个副本,
  8. // 因此,应用程序应在发出任何其他 Windows 套接字函数调用之前复制它需要的任何信息。
  9. protoent * getprotobyname( const char *name );

参数:

  1. - *name
  2. - 指向以空字符结尾的协议名称的指针。

返回值
如果没有错误发生, getprotobyname返回一个指针 protoent。否则,它会返回一个空指针,并且可以通过调用WSAGetLastError来检索特定的错误编号 。

10.getservbyname( )

简要描述:
检索与服务名称和协议相对应的服务信息。
源码:

  1. typedef struct servent {
  2. char *s_name; // 服务的官方名称。
  3. char **s_aliases; // 以NULL结尾的备用名称数组。
  4. #if ...
  5. char *s_proto; // 联系服务时使用的协议名称。
  6. #if ...
  7. short s_port; // 可以联系服务的端口号。端口号以网络字节顺序返回。
  8. #else
  9. short s_port;
  10. #endif
  11. #else
  12. char *s_proto;
  13. #endif
  14. } SERVENT, *PSERVENT, *LPSERVENT; // 存储或某项服务的名称返回名称和服务号码。
  15. servent *WSAAPI getservbyname(
  16. const char *name,
  17. const char *proto
  18. );

参数:

  1. - ***name**:
  2. - 指向以空字符结尾的服务名称的指针。
  3. - ***proto**:
  4. - 指向以空字符结尾的协议名称的指针。 如果此指针为 NULL,则 getservbyname 函数返回第一个服务条目,其中 name servent 结构的s_name 成员或servent 结构的s_aliases 成员匹配。 否则, getservbyname 匹配名称和原型。

返回值
如果没有发生错误, getservbyname 会返回一个指向servent结构的指针 。否则,它会返回一个空指针,并且可以通过调用WSAGetLastError来检索特定的错误编号 。

11.模板

简要描述:


参数:**

返回值: