⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 抢先式多线程网络蜘蛛.txt

📁 几个Internet网络编程的资料和源码
💻 TXT
字号:
抢先式多线程网络蜘蛛
    Win32 API 支持抢先式多线程网络,这是编写MFC网络蜘蛛非常有用的地方。
SPIDER工程(程序)是一个如何用抢先式多线程技术实现在网上用网络蜘蛛/机器
人聚集信息的程序。

  该工程产生一个象蜘蛛一样行动的程序,该程序为断开的URL链接检查WEB站点。
链接验证仅在href指定的链接上进行。它在一列表视图CListView中显示不断更新
的URL列表,以反映超链接的状态。本工程能用作收集、索引信息的模板,该模板
将这些信息存入到可以用于查询的数据库文件中。

  搜索引擎在WEB上使用叫作Robots(也叫爬虫,蜘蛛,蠕虫,漫步者,滑行者等等)
的程序收集信息,它从WEB上自动地聚集和索引信息,接着将这些信息存入数据库。
(注意:一个机器人将搜索一个页面,然后把这个页面上的链接作为将要索引的新
的URL的起点)用户可创建查询去查询这些数据库以发现他们需要的信息。 

  通过抢先式多线程地使用,你能索引一个基于URL链接的WEB页面,启动一个新的
线程跟随每个新的URL链接,索引一个新的URL起点。本工程使用和自定义的MDI子
框架一起使用的MDI 文档类,在下载WEB页面时显示一个编辑视图,在检查URL连接
时显示一个列表视图。另外,本工程使用了CObArray,CInternetSession,CHttpConnection,
ChttpFile和CWinThread MFC类。CWinThread类用于产生多线程来代替在CInternetSession
类中的异步模式,这种模式是从insock的16位windows平台保留下来的。SPIDER
工程使用简单的工作线程去检查URL链接,或者下载一个Web页面。CSpiderThread类
是从CWinThread类中派生的,所以,每个CSpiderThread对象可以使用CWinThread 的
MESSAGE_MAP()函数。通过在CSpiderThread类中声明"DECLARE_MESSAGE_MAP()",
用户接口可以响应用户的输入。这意味着你可以在一个Web服务器上检查URL链接的同时,
你可以从另一个Web服务器上下载或打开一个Web页面。只有在线程数超过定义为64的
MAXIMUM_WAIT_OBJECTS时,用户接口将不会响应用户的输入。在每个CSpiderThread对
象的构造函数中,我们提供了ThreadProc函数以及将传送到ThreadProc函数的线程参数。

CSpiderThread* pThread;
pThread = NULL;
pThread = new CSpiderThread(CSpiderThread::ThreadFunc,pThreadParams); // 创建一个新的 CSpiderThread 对象;

在类CSpiderThread 构造函数中我们在线程参数中设置指针CWinThread* m_pThread ,
于是我们可以指向这个线程正确的事例:
pThreadParams->m_pThread = this;

The CSpiderThread ThreadProc Function 

// 简单的工作线程函数
UINT CSpiderThread::ThreadFunc(LPVOID pParam)
{
    ThreadParams * lpThreadParams = (ThreadParams*) pParam;
    CSpiderThread* lpThread = (CSpiderThread*) lpThreadParams->m_pThread;
    
    lpThread->ThreadRun(lpThreadParams);

    // 这里使用SendMessage代替PostMessageUse,以保持当前线程数同步。
    // 如果线程数大于 MAXIMUM_WAIT_OBJECTS (64), 本程序将变得不能响应用户输入

    ::SendMessage(lpThreadParams->m_hwndNotifyProgress,
        WM_USER_THREAD_DONE, 0, (LPARAM)lpThreadParams); 
    // 删除lpThreadParams 和减少线程总数

    return 0;
}

这个结构传递给CSpiderThread ThreadProc函数
typedef struct tagThreadParams
{
    HWND m_hwndNotifyProgress;
    HWND m_hwndNotifyView;
    CWinThread* m_pThread;
    CString m_pszURL;
    CString m_Contents;
    CString m_strServerName;
    CString m_strObject;
    CString m_checkURLName;
    CString m_string;
    DWORD m_dwServiceType;
    DWORD m_threadID;
    DWORD m_Status;
    URLStatus m_pStatus;
    INTERNET_PORT m_nPort;
    int m_type;
    BOOL m_RootLinks;

}ThreadParams; 

CSpiderThread对象创建后,我们用CreatThread函数开始一个新的线程对象地执行。

    if (!pThread->CreateThread()) //开始一 CWinThread 对象地执行
    {
        AfxMessageBox("Cannot Start New Thread");
        delete pThread;
        pThread = NULL;
        delete pThreadParams;
        return FALSE;
    } 
一旦新的线程正在运行,我们使用::SengMessage函数发送消息到 CDocument's-> CListView ,这个消息带有URL链接的状态结构。
    if(pThreadParams->m_hwndNotifyView != NULL)
        ::SendMessage(pThreadParams->m_hwndNotifyView,WM_USER_CHECK_DONE, 0, (LPARAM) &pThreadParams->m_pStatus);

URL状态的结构:

typedef struct tagURLStatus
{
    CString m_URL;
    CString m_URLPage;
    CString m_StatusString;
    CString m_LastModified;
    CString m_ContentType;
    CString m_ContentLength;
    DWORD    m_Status;
}URLStatus, * PURLStatus;

  每个新的线程建立一个新的CMyInternetSession类(派生于CInternetSession)对象,
并把 EnableStatusCallback设置为TRUE,于是,我们可以在所有的InternetSession回
调时检查状态。将回调使用的dwContext ID设置为线程ID。

BOOL CInetThread::InitServer()
{
    
    try
    {
        m_pSession = new CMyInternetSession(AgentName,m_nThreadID);
        int ntimeOut = 30; // 很重要!如果设置太小回引起服务器超时,如果设置太大则回引起线程挂起。
        /*
        网络连接请求时间超时值在数毫秒级。如果连接请求时间超过这个超时值,请求将被取消。
        缺省的超时值是无限的。
        */
        m_pSession->SetOption(INTERNET_OPTION_CONNECT_TIMEOUT,1000* ntimeOut);
        
        /* 在重试连接之间的等待的延时值在毫秒级。*/
        m_pSession->SetOption(INTERNET_OPTION_CONNECT_BACKOFF,1000);
        
        /* 在网络连接请求时的重试次数。如果一个连接企图在指定的重试次数后仍失败,则请求被取消。 缺省值为5。 */
        m_pSession->SetOption(INTERNET_OPTION_CONNECT_RETRIES,1);
    m_pSession->EnableStatusCallback(TRUE);

    }
    catch (CInternetException* pEx)
    {
        // catch errors from WinINet
        //pEx->ReportError();
        m_pSession = NULL;
        pEx->Delete();
        return FALSE ;
    }

    return TRUE;
}

  在一个单或多线程程序中使用MFC WinIne类,关键是要在所有MFC WinInet类函数
周围使用try和catch块。因为互连网有时很不稳定,或者你访问的Web页面已不存在,
则这种情况下,将抛出一个CInternetException错误。


    try
    {
        // some MFC WinInet class function
    }
    catch (CInternetException* pEx)
    {
        // catch errors from WinINet
        //pEx->ReportError();
        pEx->Delete();
        return FALSE ;
    }
  最初线程数最大设置为64,你可以将它设置为从1到100的任何数。设置太高会使链
接失败,意味着你将不得不重新检查URL链接。在/cgi-bin/目录下一个连续不断地迅
猛地HTTP请求会使服务器崩溃。SPIDER 程序在1秒中发送四个HTTP请求,1分钟240个。
这也将会使服务器崩溃。在任何服务器上你检查时放仔细一点。每个服务器都有一个
请求Web文件的请求代理IP地址的日志。你或许会收到来自Web服务器管理员的龌龊的邮件。


  你可以为一些目录建立robots.txt 文件来防止这些目录被索引。这个机制通常用于
保护/cgi-bin/ 目录。CGI脚本占用更多的要检索的服务器资源。当SPIDER程序检查URL
链接时,它的目标是不太快地请求太多的文档。SPIDER程序坚持机器人拒绝的标准。
这个标准是机器人开发者之间的协议,允许WWW站点限制URL上的机器人的请求。通过
使用这个限制访问的标准,机器人将不检索Web服务器希望拒绝的任何文档。在检查根
URL前,程序检查看是否有robots.txt文件在主目录下。如果SPIDER程序发现robots.txt
文件,将放弃搜索。另外,程序也检查所有Web页面中的META标记。如果发现一个META标
记,它的NAME="ROBOTS" CONTENT ="NOINDEX,NOFOLLOW",则不索引那个页面上的URL。

创建: 
Windows 95 
MFC/VC++ 5.0 
WinInet.h 时间 9/25/97 
WinInet.lib 时间 9/16/97 
WinInet.dll 时间 9/18/97 


问题:

允许 32,767 个URL 链接在 CListView 中。
不能分析 URL的正确性 。


资料: 
Internet tools - Fred Forester 
Multithreading Applications in Win32 
Win32 Multithreaded Programming 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -