Visual C++ 2017网络编程实战
上QQ阅读APP看书,第一时间看更新

2.9 获取本机上支持的网络协议信息

可以通过函数WSAEnumProtocols检索有关可用网络传输协议的信息。该函数声明如下:

    int WSAAPI WSAEnumProtocols( LPINT        lpiProtocols,
      LPWSAPROTOCOL_INFOA lpProtocolBuffer,
      LPDWORD             lpdwBufferLength);

其中,参数lpiProtocols指向协议值数组;lpProtocolBuffer指向用WSAPROTOCOL_INFOA结构填充的缓冲区的指针;lpdwBufferLength在输入时,传递给WSAEnumProtocols的lpProtocolBuffer缓冲区中的字节数。输出时,可以传递给WSAEnumProtocols以检索所有请求信息的最小缓冲区大小。如果函数没有出现错误,WSAEnumProtocols将返回要报告的协议数;否则,将返回SOCKET_ERROR的值,并且可以通过调用WSAGetLastError来检索特定的错误代码。

值得注意的是,在调用WSAEnumProtocols之前要先调用WSAStartup函数,否则会得到WSANOTINITIALISED的错误码。WSAStartup启动对winsock dll的使用。另外,使用了WSAStartup后,结束的时候要用WSACleanup进行清理,这两个函数要配套使用。

【例2.9】获取本机上支持的网络协议信息

(1)新建一个对话框工程Demo。

(2)切换到资源视图,在对话框上放一个列表框和一个按钮。其中,列表框的ID是IDC_LIST。双击按钮,为其添加事件响应代码:

    void CDemoDlg::OnTest()
    {
    //初始化WinSock
    WSADATA WSAData;
    if (WSAStartup(MAKEWORD(2,0), &WSAData)!= 0)
    {
         return;
    }

    int nResult = 0;

    //获得需要的缓冲区大小
    DWORD nLength = 0;
    nResult = WSAEnumProtocols(NULL, NULL, &nLength);
    if (nResult != SOCKET_ERROR)
    {
         return;
    }
    if (WSAGetLastError() != WSAENOBUFS)
    {
         return;
    }

    WSAPROTOCOL_INFO* pProtocolInfo = (WSAPROTOCOL_INFO*)new BYTE[nLength];

    //获得本地计算机协议信息
    nResult = WSAEnumProtocols(NULL, pProtocolInfo, &nLength);
    if (nResult == SOCKET_ERROR)
    {
         delete[] pProtocolInfo;
         return;
    }
    for (int n = 0; n < nResult; n++)
    {
         m_ctrlList.AddString(pProtocolInfo[n].szProtocol);
    }

    delete[] pProtocolInfo;
    //清理WinSock
    WSACleanup();
    }

在DemoDlg.cpp开头包含头文件和引用库文件:

    #include <Winsock2.h>
    #pragma comment(lib,"Ws2_32.lib")

(3)保存工程并运行,运行结果如图2-13所示。

图2-13