网络编程中,InternetOpen函数是一个非常重要的函数。它的作用是初始化WinINet库。这个库提供了一些用于网络编程的函数,包括发送和接收数据、连接和断开连接等。InternetOpen函数是这些函数的基础,因此了解它的使用和用法非常重要。
InternetOpen函数的定义
InternetOpen函数是WinINet库的一部分。它定义在wininet.h中,其原型如下:
HINTERNET InternetOpen(
LPCTSTR lpszAgent,
DWORD dwAccessType,
LPCTSTR lpszProxyName,
LPCTSTR lpszProxyBypass,
DWORD dwFlags
);
其中,各参数的含义如下:
- lpszAgent:指定一个字符串,用于标识客户端程序的名称。这个参数通常是可选的,可以传入NULL。
- dwAccessType:指定访问网络的方式。可以是以下值中的一个:
- INTERNET_OPEN_TYPE_DIRECT:直接访问互联网。
- INTERNET_OPEN_TYPE_PROXY:通过代理服务器访问互联网。
- INTERNET_OPEN_TYPE_PRECONFIG:使用IE设置中的默认设置访问互联网。
- lpszProxyName:指定代理服务器的名称。如果dwAccessType不是INTERNET_OPEN_TYPE_PROXY,则该参数被忽略。可以传入NULL。
- lpszProxyBypass:指定不使用代理服务器的地址。如果dwAccessType不是INTERNET_OPEN_TYPE_PROXY,则该参数被忽略。可以传入NULL。
- dwFlags:指定一组标志,用于控制该函数的行为。可以是以下值中的一个或多个:
- INTERNET_FLAG_ASYNC:启用异步方式。
- INTERNET_FLAG_FROM_CACHE:从缓存中获取数据,而不是从服务器上获取。
- INTERNET_FLAG_OFFLINE:离线方式访问。
InternetOpen函数返回一个HINTERNET类型的句柄,该句柄表示一个初始化后的会话。
使用InternetOpen函数打开一个会话
现在,我们来看一个使用InternetOpen函数打开一个会话的示例。下面是一个简单的程序,它使用InternetOpen函数创建一个会话,然后再使用InternetCloseHandle函数关闭该会话:
#include
#include
#include
#include
int main()
{
HINTERNET hInternet;
DWORD dwAccessType;
TCHAR* lpszProxyName = 0;
TCHAR* lpszProxyBypass = 0;
DWORD dwFlags;
dwAccessType = INTERNET_OPEN_TYPE_PRECONFIG;
dwFlags = 0;
hInternet = InternetOpen(_T("MyApp"), dwAccessType, lpszProxyName, lpszProxyBypass, dwFlags);
if (hInternet == NULL)
{
fprintf(stderr, "Error: InternetOpen failed (%d)\n", GetLastError());
return 1;
}
else
{
printf("Session opened successfully!\n");
}
InternetCloseHandle(hInternet);
return 0;
}
在这个程序中,我们将访问互联网的方式设为INTERNET_OPEN_TYPE_PRECONFIG,这意味着我们使用IE中的默认设置。我们不需要指定代理服务器的名称或地址,因此将它们都设为NULL。我们不使用任何标志。
如果InternetOpen函数成功,它将返回一个非空句柄,我们可以将其用于进一步操作。如果失败,则返回NULL。这时,我们可以使用GetLastError函数获取错误代码。
在本示例中,我们只是简单地打开了一个会话,但InternetOpen函数还有更多的功能。我们将在下面的章节中讨论这些功能。
使用InternetOpen函数指定代理服务器
许多组织都使用代理服务器来保护其网络安全。这些代理服务器可以防止未经授权的访问,并帮助轻松管理网络流量。当您使用具有代理服务器的网络时,必须指定代理服务器的名称和端口号。为此,请使用InternetOpen函数的lpszProxyName参数。
下面是一个使用代理服务器的示例程序:
int main()
{
HINTERNET hInternet;
DWORD dwAccessType;
TCHAR* lpszProxyName = _T("proxy.myorg.com:8080");
TCHAR* lpszProxyBypass = 0;
DWORD dwFlags;
dwAccessType = INTERNET_OPEN_TYPE_PROXY;
dwFlags = 0;
hInternet = InternetOpen(_T("MyApp"), dwAccessType, lpszProxyName, lpszProxyBypass, dwFlags);
if (hInternet == NULL)
{
fprintf(stderr, "Error: InternetOpen failed (%d)\n", GetLastError());
return 1;
}
else
{
printf("Session opened successfully!\n");
}
InternetCloseHandle(hInternet);
return 0;
}
在这个程序中,我们使用代理服务器proxy.myorg.com,其端口号为8080。我们指定了访问网络的方式为INTERNET_OPEN_TYPE_PROXY。我们不需要指定lpszProxyBypass参数,因为我们不希望绕过代理服务器。
使用InternetOpen函数异步访问网络
当您在使用InternetOpen函数时,可以选择以异步方式执行操作。这意味着当您执行一个操作时,它不会阻止您的程序继续执行。相反,Windows将在后台处理该操作。当操作完成时,Windows会调用您的回调函数。这可以使您的程序更加响应。
为了开启异步方式,请将dwFlags参数中的INTERNET_FLAG_ASYNC标志设置为1。下面是一个使用异步方式打开会话的示例程序:
void CALLBACK openCallback(HINTERNET hInternet,
DWORD_PTR dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED)
{
printf("Session opened successfully (ASYNC)!\n");
}
else
{
fprintf(stderr, "Error: InternetOpen failed (%d)\n", dwStatusInformationLength);
}
}
int main()
{
HINTERNET hInternet;
DWORD dwAccessType;
TCHAR* lpszProxyName = 0;
TCHAR* lpszProxyBypass = 0;
DWORD dwFlags;
dwAccessType = INTERNET_OPEN_TYPE_PRECONFIG;
dwFlags = INTERNET_FLAG_ASYNC;
hInternet = InternetOpen(_T("MyApp"), dwAccessType, lpszProxyName, lpszProxyBypass, dwFlags);
if (hInternet == NULL)
{
WaitForSingleObject(GetCurrentThread(), INFINITE);
return 1;
}
else
{
InternetSetStatusCallback(hInternet, openCallback);
SleepEx(INFINITE, TRUE);
}
return 0;
}
此程序中,在InternetOpen函数的dwFlags参数中设置了INTERNET_FLAG_ASYNC标志,以开启异步方式。在主函数中,我们首先创建了一个会话,然后使用InternetSetStatusCallback函数注册了一个回调函数openCallback,该函数将在会话创建时被调用。
接下来,我们使用SleepEx(INFINITE, TRUE)函数使程序进入无限休眠状态,直到回调函数被调用。
当我们在回调函数中处理异步操作时,我们需要处理多个不同的状态。例如,当操作完成时,您需要检查状态是否为INTERNET_STATUS_REQUEST_COMPLETE。每种状态下回调函数的行为都不同,具体取决于您的需求。
控制InternetOpen函数的行为
当调用InternetOpen函数时,可以使用dwFlags参数指定更多行为。下面是一些可能有用的标志:
- INTERNET_FLAG_CACHE_IF_NET_FAIL:如果无法连接到服务器,则从缓存中获取数据。
- INTERNET_FLAG_HYPERLINK:使URL可以像超链接一样单击。因此,当URL打开时,浏览器会在一个新标签页中加载页面。
- INTERNET_FLAG_PRAGMA_NO_CACHE:禁用缓存,以确保获取最新数据。
例如,我们可以使用以下代码使用INTERNET_FLAG_CACHE_IF_NET_FAIL标志打开会话:
int main()
{
HINTERNET hInternet;
DWORD dwAccessType;
TCHAR* lpszProxyName = 0;
TCHAR* lpszProxyBypass = 0;
DWORD dwFlags;
dwAccessType = INTERNET_OPEN_TYPE_PRECONFIG;
dwFlags = INTERNET_FLAG_CACHE_IF_NET_FAIL;
hInternet = InternetOpen(_T("MyApp"), dwAccessType, lpszProxyName, lpszProxyBypass, dwFlags);
if (hInternet == NULL)
{
fprintf(stderr, "Error: InternetOpen failed (%d)\n", GetLastError());
return 1;
}
else
{
printf("Session opened successfully (INTERNET_FLAG_CACHE_IF_NET_FAIL)!\n");
}
InternetCloseHandle(hInternet);
return 0;
}
当您使用INTERNET_FLAG_CACHE_IF_NET_FAIL标志时,如果无法连接到服务器,则WinINet将尝试从缓存中获取请求的数据。
结论
InternetOpen函数是WinINet库的一个非常重要的函数,它是发送和接收数据、连接和断开连接等网络编程函数的基础。在编写网络编程应用程序时,理解InternetOpen的用法和应用非常重要。通过本文的介绍,您应该对InternetOpen函数的作用及用法有了一个更好的了解。