zoukankan      html  css  js  c++  java
  • 第23章 尝试互联网(4)【全书完】

    23.4 WinInet和FTP

    (1)WinInet接口(含HTTP、FTP)及FTP函数层次关系

     

    (2)Ftp函数介绍

      ①InternetOpen——初始化,它告诉 Internet DLL 初始化内部数据结构并准备接收应用程序之后的其他调用。

    参数

    含义

    LPCTSTR lpszAgent

    调用WinInet函数的应用程序名字,在HTTP协议中作为用户代理项

    DWORD   dwAccessType

    访问要求类型:

    INTERNET_OPEN_TYPE_DIRECT:解析所有本地主机,使用直接连接网络。

    INTERNET_OPEN_TYPE_PRECONFIG:获取代理或直接从注册表中的配置,使用代理连接网络。

    INTERNET_OPEN_TYEP_PRECONFIG_WITH_NO_AUTOPROXY:返回注册表中代理或直接配置,并防止Microsoft Jscript或INS文件的使用

    INTERNET_OPEN_TYPE_PROXY:为代理传递请求

    LPCTSTR lpszProxyName

    当dwAccessType指定为INTERNET_OPEN_TYPE_PROXY时,为代理服务器名字。

    LPCTSTR lpszProxyBypass

    指定一个字符串,它提定一个可选的主机名列表或IP地址

    DWORD   dwFlags

    INTERNET_FLAG_ASYNC:仅作用于在该函数返回句柄的子句柄上的异步请求

    INTERNET_FLAG_FROM_CACHE:不做网络请求,所以的实体由缓存给出,如果请求的条目不在缓存中,会返回ERROR_FILE_NOT_FOUND错误。

    INTERNET_FLAG_OFFLINE:与INTERNET_FLAG_FROM_CACHE一样。

        举例:hIntSession = InternetOpen(szAppName,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,INTERNET_FLAG_ASYNC);

      ②InternetConnect——建立 Internet 的连接,返回连接句柄

    参数

    含义

    HINTERNET hInternet

    InternetOpen返回的句柄

    LPCTSTR       lpszServerName

    连接的IP或者主机名

    INTERNET_PORT nServerPort

    连接的端口。如0,则为默认端口

    LPCTSTR       lpszUsername

    用户名,如无置NULL

    LPCTSTR       lpszPassword

    密码,如无置NULL

    DWORD         dwService

    使用的服务类型,可以使用以下

    INTERNET_SERVICE_FTP(1):连接到一个FTP服务器

    INTERNET_SERVICE_GOPHER(2):Gopher服务器

    INTERNET_SERVICE_HTTP(3):连接到一个 HTTP 服务器上

    DWORD         dwFlags

    文档传输形式及缓存标记。一般置0。

    DWORD_PTR     dwContext

    当使用回叫信号时, 用来识别应用程序的前后关系

    返回值:非0——成功;0——失败,要用InternetCloseHandle来关闭这个句柄

      ③FtpFindFirstFile——是用来设置ftp当前目录的

    参数

    含义

    HINTERNET hConnect

    InternetConnect返回的FTP会话句柄

    LPCTSTR lpszSearchFile

    在FTP服务器上特定的目录里,要查询的指定名称的目录或文件名的文件,还可以使用通配符查找(如*、?)

    LPWIN32_FIND_DATA lpFindFileData

    就是用来保存查找后,所返回的文件的信息

    DWORD         dwFlags

    文档传输形式及缓存标记。一般置0。

    DWORD_PTR     dwContext

    当使用回叫信号时, 用来识别应用程序的前后关系。 一般为0

    返回值:有效句柄表示成功。NULL表示失败,可用GetLastError返回错误代码。

      ④InternetFindNextFile——查找下一个文件或目录

       参数

    含义

    HINTERNET hConnect

    hFind 是 FtpFindFirstFile 调用所返回的句柄

    LPWIN32_FIND_DATA lpFindFileData

    用来保存查找后,所返回的文件的信息

    返回值:如果调用成功, 返回 True,否则为False,可进一步调用GetLastError查询错误代码,如果为 ERROR_NO_MORE_FILES表明再没有文件存在了。边查找,边可以从lpFindFileData提取文件名/目录名。

      ⑤FtpGetFile——下载文件到本地磁盘

    参数

    含义

    HINTERNET hConnect

    InternetConnect返回的FTP会话句柄

    LPCTSTR lpszRemoteFile

    FTP服务器上的文件名

    LPCTSTR lpszNewFile

    本地机上创建的文件

    BOOL fFailIfExists

    0——替换本地文件

    1——如果本地文件已经存在则取消

    DWORD dwFlagsAndAttributes

    用来指定本地文件的文件属性(详细参考CreateFile函数)

    FILE_ATTRIBUTE_NORMAL、FILE_ATTRIBUTE_HIDDEN、

    FILE_ATTRIBUTE_READONLY、FILE_ATTRIBUTE_ARCHIVE等

    DWORD dwFlags

    FTP_TRANSFER_TYPE_ASCII(1):用ASCII传输文件

    FTP_TRANSFER_TYPE_BINARY(2):是用二进制传输文件

    DWORD dwContext

    当使用回叫信号时, 用来识别应用程序的前后关系。 一般为0

    返回值:有效句柄表示成功。NULL表示失败,可用GetLastError返回错误代码。

    【UpdDemo程序】——读取FTP服务器上的文件

    效果图
                                               服务器上的目录结构                                                                      正在从FTP下载文件    

                                                 

    软件运行时截图

    /*------------------------------------------------------------
       UPDDEMO.C --   Demonstrates Anonymous FTP Access
                        (c) Charles Petzold, 1998
      ------------------------------------------------------------*/
    
    #include <windows.h>
    #include <process.h>
    #include <wininet.h>
    #include "resource.h"
    
    #pragma  comment(lib,"WININET.LIB")
    
    //用户自定义消息
    #define WM_USER_CHECKFILE (WM_USER + 1)
    #define WM_USER_GETFILES  (WM_USER + 2)
    
    //FTP下载的信息
    #define FTPSERVER    TEXT("ftp.5iedu.net")
    #define USERNAME     TEXT("rollingstone")
    #define PASSWORD     TEXT("approach304304")
    #define DIRECTORY     TEXT("/rollingstone/web")
    #define TEMPLATE TEXT("UD??????.TXT")  //指定文件名格式的模版(其中的?为通配符,eg.UD201507.TXT)
    
    //用来存储文件名和内容的结构体
    typedef struct
    {
        TCHAR* szFileName;
        char*  szContents;
    }FILEINFO,*PFILEINFO;
    
    typedef struct
    {
        int iNum;
        FILEINFO info[1];
    }FILELIST,*PFILELIST;
    
    typedef struct   //供子线程使用的结构体
    {
        BOOL bContinue;
        HWND hwnd;
    }PARAMS,*PPARAMS;
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    BOOL    CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
    VOID    FtpThread(PVOID);
    
    //程序所用到的其他函数的声明
    FILELIST* GetFileList(VOID);
    int    Compare(const FILEINFO *, const FILEINFO *);
    VOID   ButtonSwitch(HWND, HWND, TCHAR*);
    
    TCHAR szAppName[] = TEXT("UpdDemo");
    HINSTANCE  hInst;
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int iCmdShow)
    {
         HWND         hwnd ;
         MSG          msg ;
         WNDCLASS     wndclass ;
    
         hInst = hInstance;
    
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
         wndclass.lpfnWndProc   = WndProc ;
         wndclass.cbClsExtra    = 0 ;
         wndclass.cbWndExtra    = 0 ;
         wndclass.hInstance     = hInstance ;
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
         wndclass.lpszMenuName  = NULL ;
         wndclass.lpszClassName = szAppName ;
    
         if (!RegisterClass (&wndclass))
         {
              MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
                          szAppName, MB_ICONERROR) ;
              return 0 ;
         }
         
         hwnd = CreateWindow (szAppName,                  // window class name
                              TEXT ("Update Demo with Anonymous FTP"), // window caption
                              WS_OVERLAPPEDWINDOW | WS_VSCROLL,        // window style
                              CW_USEDEFAULT,              // initial x position
                              CW_USEDEFAULT,              // initial y position
                              CW_USEDEFAULT,              // initial x size
                              CW_USEDEFAULT,              // initial y size
                              NULL,                       // parent window handle
                              NULL,                       // window menu handle
                              hInstance,                  // program instance handle
                              NULL) ;                     // creation parameters
         
         ShowWindow (hwnd, iCmdShow) ;
         UpdateWindow (hwnd) ;
         
         //主窗口显示后,检查是否存在最新的文件
         SendMessage(hwnd, WM_USER_CHECKFILE, 0, 0);
    
         while (GetMessage (&msg, NULL, 0, 0))
         {
              TranslateMessage (&msg) ;
              DispatchMessage (&msg) ;
         }
         return msg.wParam ;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static int cxClient, cyClient, cxChar, cyChar;
        static FILELIST* pList;
        SCROLLINFO    si;
        HDC         hdc;
        PAINTSTRUCT ps;
        SYSTEMTIME  st;
        TCHAR   szFileName[MAX_PATH];
        int     i;
    
        switch (message)
        {
        case WM_CREATE:
            cxChar = LOWORD(GetDialogBaseUnits());
            cyChar = HIWORD(GetDialogBaseUnits());
            return 0;
    
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            si.cbSize = sizeof(SCROLLINFO);
            si.fMask = SIF_RANGE | SIF_PAGE;
            si.nMin = 0;
            si.nMax = pList ? pList->iNum - 1 : 0;
            si.nPage = cyClient / cyChar;
            SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
            return 0;
    
        case WM_VSCROLL:
            si.cbSize = sizeof(SCROLLBARINFO);
            si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE;
            GetScrollInfo(hwnd, SB_VERT, &si);
            
            switch (LOWORD(wParam))
            {
            case SB_LINEDOWN:  si.nPos += 1; break;
            case SB_LINEUP:    si.nPos -= 1; break;
            case SB_PAGEDOWN:  si.nPos += si.nPage; break;
            case SB_PAGEUP:    si.nPos -= si.nPage; break;
            case SB_THUMBPOSITION: si.nPos = HIWORD(wParam); break;
            default:
                return 0;
            }
            si.fMask = SIF_POS;
            SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
            InvalidateRect(hwnd, NULL, TRUE);
            return 0;
    
        case WM_USER_CHECKFILE:
            //获得系统日期、文件名(年和月格式)
            GetSystemTime(&st);
            wsprintf(szFileName, TEXT("UD%04i%2i.TXT"), st.wYear, st.wMonth);
    
            //检查一下文件是否存在,如果存在,则读取所有文件
            if (GetFileAttributes(szFileName) !=(DWORD)-1)
            {
                SendMessage(hwnd, WM_USER_GETFILES, 0, 0);
                return 0;
            }
    
            //如果文件不存在,则从Internet中获取
            //但首先要检测磁盘的类型,当参数为NULL时,表示当前目录的驱动器类型
            //如果程序当前的目录是在光驱上的,则退出(因为后面要拷贝文件到程序
            //所在目录下。
            if (DRIVE_CDROM == GetDriveType(NULL))
            {
                MessageBox(hwnd, TEXT("Cannot run this program from CD-ROM!"),
                    szAppName, MB_OK | MB_ICONEXCLAMATION);
                return 0;
            }
    
            //询问用户是否要连接到网络
            if (IDYES == MessageBox(hwnd,
                                    TEXT("Update information from Internet?"),
                                    szAppName,
                                    MB_YESNO | MB_ICONQUESTION))
                    DialogBox(hInst, szAppName, hwnd, DlgProc);
    
            //更新显示
            SendMessage(hwnd, WM_USER_GETFILES, 0, 0);
            return 0;
    
        case WM_USER_GETFILES:
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            ShowCursor(TRUE);
    
            //从磁盘文件中读取所有的文件列表
            pList = GetFileList(); 
            ShowCursor(FALSE);
            SetCursor(LoadCursor(NULL, IDC_ARROW));
    
            //模拟发送一个WM_SIZE消息来改变滚动条和重绘(因为滚动条的大小与文件数量有关)
            SendMessage(hwnd, WM_SIZE, 0, MAKELONG(cxClient, cyClient));
            InvalidateRect(hwnd, NULL, TRUE);
            return 0;
    
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
    
            //TA_UPDATECP:每次文字输出调用后当前基准点改变。当前位置作为基准点
            SetTextAlign(hdc, TA_UPDATECP);
            
            si.cbSize = sizeof(SCROLLINFO);
            si.fMask = SIF_POS;
            GetScrollInfo(hwnd, SB_VERT, &si);
    
            if (pList)
            {
                for (i = 0; i < pList->iNum;i++)
                {
                    MoveToEx(hdc, cxChar, (i - si.nPos)*cyChar, NULL);
                    TextOut(hdc, 0, 0, pList->info[i].szFileName, lstrlen(pList->info[i].szFileName));
                    TextOut(hdc, 0, 0, TEXT(""), lstrlen(TEXT("")));
                    TextOutA(hdc, 0, 0, pList->info[i].szContents, strlen(pList->info[i].szContents));
                }
            }
    
            EndPaint(hwnd, &ps);
            return 0;
    
        case WM_DESTROY:
            if (pList)
            {
                //for (i = 0; i < pList->iNum; i++)
                //{
                //    if (pList->info[i].szFileName)
                //        free(pList->info[i].szFileName);
                //    if (pList->info[i].szContents)
                //        free(pList->info[i].szContents);
                //}
    
                //free(pList->info);
            }
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    
    BOOL    CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static PARAMS params;
        switch (message)
        {
        case WM_INITDIALOG:
            params.bContinue = TRUE;
            params.hwnd = hwnd;
            _beginthread(FtpThread, 0, &params);
            return TRUE;
    
        case WM_COMMAND:
            switch (LOWORD(wParam))
            {
            case IDCANCEL:
                params.bContinue = FALSE;
                return TRUE;
    
            case IDOK:
                EndDialog(hwnd, 0);
                return TRUE;
            }
            return FALSE;
    
        case WM_CLOSE:
            EndDialog(hwnd, FALSE);
            return TRUE;
        }
        return FALSE;
    }
    
    //FtpThread:从FTP服务器读取文本,并拷贝到本地磁盘中
    VOID    FtpThread(PVOID parg)
    {
        BOOL bSuccess;
        PPARAMS pparams;
        HWND hwndStatus, hwndButton;
        HINTERNET hIntSession, hFtpSession, hFind;
        TCHAR  szBuffer[64];
        WIN32_FIND_DATA  finddata;
    
        pparams = (PARAMS*)parg;
        hwndStatus = GetDlgItem(pparams->hwnd, IDC_STATUS);
        hwndButton = GetDlgItem(pparams->hwnd, IDCANCEL);
    
        //打开Internet会话
        hIntSession = InternetOpen(szAppName, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 
                                      INTERNET_FLAG_PASSIVE); //INTERNET_FLAG_ASYNC,本例用异步会不成功
        if (NULL == hIntSession)
        {
            wsprintf(szBuffer, TEXT("InternetOpen error %i"), GetLastError());
            ButtonSwitch(hwndStatus, hwndButton, szBuffer);
            _endthread();
        }
    
        SetWindowText(hwndStatus, TEXT("Internet session opened..."));
    
        //检查用户是否按了取消按钮
        if (!pparams->bContinue)
        {
            InternetCloseHandle(hIntSession);
            ButtonSwitch(hwndStatus, hwndButton, NULL);
            _endthread();
        }
    
        //打开FTP会话
        hFtpSession = InternetConnect(hIntSession, FTPSERVER, INTERNET_DEFAULT_FTP_PORT, USERNAME,
                                             PASSWORD, INTERNET_SERVICE_FTP, 0, 0);
        if (NULL == hFtpSession)
        {
            wsprintf(szBuffer, TEXT("InternetConnect error %i"), GetLastError());
            ButtonSwitch(hwndStatus, hwndButton, szBuffer);
            InternetCloseHandle(hIntSession);
            _endthread();
        }
        SetWindowText(hwndStatus, TEXT("Ftp session opened..."));
    
        //检查用户是否按了取消按钮
        if (!pparams->bContinue)
        {
            InternetCloseHandle(hFtpSession);
            InternetCloseHandle(hIntSession);
            ButtonSwitch(hwndStatus, hwndButton, NULL);
            _endthread();
        }
    
        //设置FTP当前目录
        bSuccess = FtpSetCurrentDirectory(hFtpSession, DIRECTORY);
        if (!bSuccess)
        {
            wsprintf(szBuffer, TEXT("Cannot set directory to %s"),DIRECTORY);
            InternetCloseHandle(hFtpSession);
            InternetCloseHandle(hIntSession);
            ButtonSwitch(hwndStatus, hwndButton, szBuffer);
            _endthread();
        }
    
        SetWindowText(hwndStatus, TEXT("Directory found..."));
    
        //检查用户是否按了取消按钮
        if (!pparams->bContinue)
        {
            InternetCloseHandle(hFtpSession);
            InternetCloseHandle(hIntSession);
            ButtonSwitch(hwndStatus, hwndButton, NULL);
            _endthread();
        }
    
        //获取第1个匹配特征文件名的文件
        hFind = FtpFindFirstFile(hFtpSession, TEMPLATE, &finddata, 0, 0);
        if (NULL == hFind)
        {
            InternetCloseHandle(hFtpSession);
            InternetCloseHandle(hIntSession);
            ButtonSwitch(hwndStatus, hwndButton, TEXT("Cannot find files"));
            _endthread();
        }
    
        //将所有文件名符合“UD??????.TXT”的文件下载到本地磁盘的当前目录下
        do 
        {
            //检查用户是否按了取消按钮
            if (!pparams->bContinue)
            {
                InternetCloseHandle(hFtpSession);
                InternetCloseHandle(hIntSession);
                ButtonSwitch(hwndStatus, hwndButton, NULL);
                _endthread();
            }
    
            
            wsprintf(szBuffer, TEXT("Reading file %s..."), finddata.cFileName);
            SetWindowText(hwndStatus, szBuffer);
            
            //将文件从Ftp服务器下载到本地磁盘,如果本地磁盘己经存在,则失败
            FtpGetFile(hFtpSession, finddata.cFileName, finddata.cFileName, TRUE,
                           FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY, 0);
        } 
        while (InternetFindNextFile(hFind,&finddata));
        
        InternetCloseHandle(hFind);
        InternetCloseHandle(hFtpSession);
        InternetCloseHandle(hIntSession);
        ButtonSwitch(hwndStatus, hwndButton, TEXT("Internet Download Complete"));
    }
    
    //ButtonSwitch:用来显示最后的状态并将“取消”按钮改变为“OK”按钮
    VOID  ButtonSwitch(HWND hwndStatus, HWND hwndButton, TCHAR* szText)
    {
        if (szText)
            SetWindowText(hwndStatus, szText);
        else
            SetWindowText(hwndStatus, TEXT("Internet Session Cancelled"));
    
        SetWindowText(hwndButton, TEXT("OK"));
        SetWindowLong(hwndButton, GWL_ID, IDOK);
    }
    
    //从磁盘中读取文件并把各文件名和内容保存在指定的缓冲区中
    FILELIST* GetFileList(VOID)
    {
        DWORD dwRead;
        FILELIST* pList;
        int iNum,iSize;
        HANDLE  hFile, hFind;
    
        WIN32_FIND_DATA finddata;
    
        hFind = FindFirstFile(TEMPLATE, &finddata);
        if (hFind == INVALID_HANDLE_VALUE)
            return NULL;
    
        pList = NULL;
        iNum = 0;
        do 
        {
            //打开文件并获得文件大小
            hFile = CreateFile(finddata.cFileName, GENERIC_READ, FILE_SHARE_READ,
                                NULL, OPEN_EXISTING, 0, NULL);
            if (hFile == INVALID_HANDLE_VALUE)
                continue;
    
            iSize = GetFileSize(hFile, NULL);
            if (iSize == (DWORD)-1)
            {
                CloseHandle(hFile);
                continue;
            }
    
            //重新分配FILELIST结构体,以增加一个新的项目
            pList = realloc(pList, sizeof(FILELIST)+iNum*sizeof(FILEINFO));
            //分配空间以存储文件名
            pList->info[iNum].szFileName = malloc(lstrlen(finddata.cFileName) + sizeof(TCHAR));
            lstrcpy(pList->info[iNum].szFileName, finddata.cFileName);
            //分配空间以存储文件的内容
            pList->info[iNum].szContents = malloc(iSize + 1);
            ReadFile(hFile, pList->info[iNum].szContents, iSize, &dwRead, NULL);
            pList->info[iNum].szContents[iSize] = 0;
            CloseHandle(hFile);
            iNum++;
        } 
        while (FindNextFile(hFind,&finddata));
    
        //按文件名排序(降序)
        qsort(pList->info, iNum, sizeof (FILEINFO), Compare);
        pList->iNum = iNum;
        return pList;
    }
    
    int    Compare(const FILEINFO * pInfo1, const FILEINFO * pInfo2)
    {
        return  lstrcmp(pInfo2->szFileName, pInfo1->szFileName); 
    }

    //resource.h

    //{{NO_DEPENDENCIES}}
    // Microsoft Visual C++ 生成的包含文件。
    // 供 UpdDemo.rc 使用
    //
    #define IDC_STATUS                      1001
    
    // Next default values for new objects
    // 
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        102
    #define _APS_NEXT_COMMAND_VALUE         40001
    #define _APS_NEXT_CONTROL_VALUE         1002
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif

    //UdpDemo.rc

    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"
    
    #define APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 2 resource.
    //
    #include "winres.h"
    
    /////////////////////////////////////////////////////////////////////////////
    #undef APSTUDIO_READONLY_SYMBOLS
    
    /////////////////////////////////////////////////////////////////////////////
    // 中文(简体,中国) resources
    
    #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
    LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
    
    #ifdef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // TEXTINCLUDE
    //
    
    1 TEXTINCLUDE 
    BEGIN
        "resource.h"
    END
    
    2 TEXTINCLUDE 
    BEGIN
        "#include ""winres.h""
    "
        ""
    END
    
    3 TEXTINCLUDE 
    BEGIN
        "
    "
        ""
    END
    
    #endif    // APSTUDIO_INVOKED
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // Dialog
    //
    
    UPDDEMO DIALOGEX 0, 0, 211, 44
    STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
    CAPTION "Internet Download"
    FONT 8, "MS Shell Dlg", 400, 0, 0x1
    BEGIN
        PUSHBUTTON      "Cancel",IDCANCEL,83,26,50,14
        CTEXT           "",IDC_STATUS,15,11,178,8
    END
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // DESIGNINFO
    //
    
    #ifdef APSTUDIO_INVOKED
    GUIDELINES DESIGNINFO
    BEGIN
        "UPDDEMO", DIALOG
        BEGIN
            LEFTMARGIN, 7
            RIGHTMARGIN, 204
            TOPMARGIN, 7
            BOTTOMMARGIN, 42
        END
    END
    #endif    // APSTUDIO_INVOKED
    
    #endif    // 中文(简体,中国) resources
    /////////////////////////////////////////////////////////////////////////////
    
    
    
    #ifndef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 3 resource.
    //
    
    
    /////////////////////////////////////////////////////////////////////////////
    #endif    // not APSTUDIO_INVOKED

    23.5 其他网络常用函数

    (1)和主机名相关的函数

      ①gethostbyname——将主机名转成IP

    参数

    含义

    const char FAR *name

    需要解析的主机名字符串

    返回值——指向WinSock内部缓冲区一个HOSTENT结构体的指针。(因为一个主机名可能对应多个IP地址)

     【图解HOSTENT结构体】

     

      ②gethostbyaddr函数——将IP地址转换成主机名

    参数

    含义

    const char FAR *addr

    指向IP地址的指针(注意,不是字符串,而是网络字节顺序的32位IP)

    int len

    IP地址的数据长度,当然是4个字节了

    int type

    地址的类型,一般为AF_INET

    返回值

    失败时返回0。

    成功时返回HOSTENT结构体,其中的h_name指向转换后的主机名

       ③gethostname——获取本地计算机的主机名

    参数

    含义

    const char FAR *addr

    在指定的缓冲区返回本地计算机的主机名字符串

    int namelen

    指定缓冲区的大小

    (2)获取套接字两端的地址信息

      ①getpeername——获取对端的IP地址和端口

    参数

    含义

    SOCKET s

    套接字句柄

    struct sockaddr FAR *name

    指向SOCKADDR_IN结构体的指针,函数会将对端的IP和端口信息

    int FAR *namelen

    指定缓冲区的长度

    返回值

    成功为0,失败SOCKET_ERROR。

    注意:该函数不是获取对端IP和端口的唯一方法。如果连接是本机主动发起,那些连接时就己知这些信息。如果连接是对方发起,在accept函数时,也可以得到对方的地址信息。

      ②getsockname函数——获取本地端使用的IP地址和端口(特别是多网卡和系统自动选择端口时,可以通过该函数获知)。该函数也是将信息返回在sockaddr_in结构体中。

     【其他网络函数测试程序】

    #include <stdio.h>
    #include "winsock2.h"
    
    #pragma comment(lib,"ws2_32.lib")
    
    //显示HOSTENT结构体的内容
    void ShowHostEntInfo(HOSTENT* phe)
    {
        char** ppIPList;
        char** ppAlias;
    
        SOCKADDR_IN sa;
    
        sa.sin_family = phe->h_addrtype;
        
        //只处理IP4
        if (phe->h_addrtype == AF_INET)
        {
            printf("正式主机名称:%s
    ", phe->h_name);
            
            //主机可能有多个别名,分别打印出来
            for (ppAlias = phe->h_aliases; *ppAlias != NULL; ppAlias++) //ppAlias是个指针,所以++增量为4个字节
                printf("alias:%s
    ", *ppAlias);
    
            //将IP地址打印出来
            for (ppIPList = phe->h_addr_list; *ppIPList != NULL; *ppIPList++)
            {
                sa.sin_addr.S_un.S_addr = (ULONG)(*(int*)*ppIPList); //取出来的IP,本身就是网络字节序的
                printf("address:%s
    ", inet_ntoa(sa.sin_addr)); 
            }
        }    
    }
    
    int main()
    {
        WSADATA wsa;
        HOSTENT* phe;
        ULONG IP;
        char szBuffer[20];
    
        //char szHostName[] = "SantaClaus-PC";
        //char szHostName[] = "localhost";
        char szHostName[] = "www.baidu.com";
    
        WSAStartup(MAKEWORD(2, 0), &wsa);
    
        printf("将域名(www.baidu.com)或主机名转化为IP地址:
    ");
    
        //通过gethostbyname将域名或主机名转化为IP地址
        phe = gethostbyname(szHostName);
        if (phe !=NULL)
            ShowHostEntInfo(phe);
    
        printf("
    将IP地址(127.0.0.1)转为主机名:
    ");
        //通过gethostbyaddr将IP地址转为主机名
        IP =inet_addr("127.0.0.1");
        phe = gethostbyaddr((char*)&IP, 4, AF_INET);
        if (phe != NULL)
            ShowHostEntInfo(phe);
    
        //获取本机主机名
        gethostname(szBuffer, sizeof(szBuffer));
        printf("
    通过gethostname获取本机主机名:%s
    
    ",szBuffer);
    
        WSACleanup();
        return 0;
    
    }
  • 相关阅读:
    8088汇编跳转和PSW状态字寄存器
    Delphi的函数指针
    服务器系统及软件常见漏洞
    TGraphiControl响应WM_MOUSEMOVE的过程(以TPaintBox为例)good
    两个奇怪的取地址符号
    把x指针指向的4个字节次序颠倒过来
    DELPHI中的消息处理机制(三种消息处理方法的比较,如何截断消息)
    探索C++的底层机制
    setprecision、fixed、showpoint的用法总结(经典!!超经典!!)
    段寄存器和8种地址寻址方式
  • 原文地址:https://www.cnblogs.com/5iedu/p/4715321.html
Copyright © 2011-2022 走看看