01启动(关闭)套接字

发布时间 2023-10-14 18:14:18作者: 西兰花战士

windows操作系统为我们提供了一套底层Socket API,用于实现网络通信。在我们编写的程序中,如果需要引用该网络库,需要实现以下几步:

1、包含头文件

1 #include <WinSock2.h>

其中,头文件<WinSock2.h>表示Windows Socket 第二版,第一版为 <winsock.h>。

2、引入库文件

1 #pragma comment(lib,"ws2_32.lib")

上边代码是将ws2_32.lib库文件引入到工程,该库中包含了<WinSock2.h>头文件中的实现部分。需要注意的是,不管是32位编译环境还是64位编译环境,都是使用该库文件。如果需要使用第一版的网络库,可以引入"wsock32.lib"。

3、打开网络库

在使用Socket套接字之前,需要调用WSAStartup函数启动Win Socket套接字服务,该函数定义如下:

int WSAStartup(
    WORD        wVersionRequired,
    LPWSADATA    lpWSAData
);

参数

  • wVersionRequired:用于指定Win Socket套接字版本。其中,低字节代表主版本,高字节代表次版本。
  • lpWSAData:输出型参数,指向WSADATA类型的指针,该指针中保存Win Socket套接字实现的详细信息。

返回值

如果该函数执行成功,WSAStartup函数返回0。否则,它将返回如下错误代码:

错误代码 含义
WSASYSNOTREADY 10091  底层网络子系统尚未准备好进行网络通信。
WSAVERNOTSUPPORTED 10092 不支持给定的版本号,检查是不是将主版本号设置为0。
WSAEINPROGRESS 10036 当一个阻塞函数正在进行时,调用任何Windows Sockets API函数均返回此错误。
WSAEPROCLIM 10067 Windows Sockets实现可能限制同时使用它的应用程序的数量,如果达到此限制,则返回该错误。
WSAEFAULT 10014 lpWSAData指针错误,检查是否传入nullptr。

 

 

 

 

 

版本号

Win Socket当前支持的最大版本号为2.2版,当前支持的所有版本为:1.0、1.1、2.0、2.1、2.2。

可以通过 MAKEWORD 宏构造一个版本号,例如:

//MAKEWORD(lowbyte, highbyte)
WORD wdVersion = MAKEWORD(2, 1);      //构造2.1版本

当输入不存在的版本号时,有以下几种情况:

  • 有主版本号,没副版本号:编译返回该主版本号的最大副版本号。例如:输入2.3,则使用2.2版本。
  • 超过最大版本号或者主版本号为负数:则返回系统能提供的最大版本号。例如,输入3.3,返回2.2版本。
  • 主版本号是0:网络库打开失败,返回WSAVERNOTSUPPORTED错误码,不支持的套接字版本。

WSAData结构体

该结构保存了Win Socket套接字实现的详细信息。该结构体定义如下:

1 struct WSAData {
2   WORD           wVersion;          //当前使用的版本。
3   WORD           wHighVersion;      //当前支持的最高版本。
4   unsigned short iMaxSockets;       //[2版本弃用]返回当前可用的Socket数量
5   unsigned short iMaxUdpDg;         //[2版本弃用]UDP数据报信息大小
6   char           *lpVendorInfo;     //[2版本弃用]供应商特定信息
7   char           szDescription[WSADESCRIPTION_LEN + 1];    //以NULL结尾的ASCII字符串,描述Win Socket套接字实现说明。
8   char           szSystemStatus[WSASYS_STATUS_LEN + 1];    //以NULL结尾的ASCII字符串,描述相关状态或配置信息。
9 };

4、关闭网络库

当Win Socket套接字执行完毕后,需要调用WSACleanup函数关闭套接字,释放分配的资源,该函数定义如下:

1 int WSACleanup();

返回值

如果该函数执行成功,则返回值为0,否则,返回下列错误代码:

错误代码 含义
WSANOTINITIALISED 10093 在使用该函数之前,必须成功调用WSAStartup
WSAENETDOWN 10050 套接字操作遇到一个不活动的网络。此错误可能指示网络系统(例如WinSock DLL运行的协议栈)、网络接口或本地网络本身发生了一个严重的失败。
WSAEINPROGRESS 10036 一个阻塞操作正在执行。Windows Sockets只允许一个任务(或线程)在同一时间可以有一个未完成的阻塞操作,如果此时调用了任何函数,将返回该错误。

 

 

 

 

 

 

示例程序

 1 #include <iostream>
 2 #include <WinSock2.h>
 3 #pragma comment(lib,"ws2_32.lib")
 4 using namespace std;
 5 
 6 const unsigned short MajorVersion = 2;        //主版本号
 7 const unsigned short MinorVersion = 2;        //副版本号
 8 
 9 int main()
10 {
11     WORD wdVersion = MAKEWORD(MajorVersion, MinorVersion);
12     WSAData wSocketInfo;
13     int nRet = WSAStartup(wdVersion, &wSocketInfo);
14     if (nRet != 0)
15     {
16         std::cout << "open error!" << std::endl;
17         return;
18     }
19 
20     //版本检验
21     if (MinorVersion != HIBYTE(wSocketInfo.wVersion) ||
22         MajorVersion != LOBYTE(wSocketInfo.wVersion))
23     {
24         assert(0);
25         WSACleanup();
26         return 0;
27     }
28     ...
29     
30     WSACleanup();
31 }

 

参考

Windows Sockets 错误码及出错原因-chenshko-ChinaUnix博客