码迷,mamicode.com
首页 > 其他好文 > 详细

第23章 尝试互联网(4)【全书完】

时间:2015-08-09 16:58:09      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:

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\0"
END

2 TEXTINCLUDE 
BEGIN
    "#include ""winres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
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\n", phe->h_name);
        
        //主机可能有多个别名,分别打印出来
        for (ppAlias = phe->h_aliases; *ppAlias != NULL; ppAlias++) //ppAlias是个指针,所以++增量为4个字节
            printf("alias:%s\n", *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\n", 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地址:\n");

    //通过gethostbyname将域名或主机名转化为IP地址
    phe = gethostbyname(szHostName);
    if (phe !=NULL)
        ShowHostEntInfo(phe);

    printf("\n将IP地址(127.0.0.1)转为主机名:\n");
    //通过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("\n通过gethostname获取本机主机名:%s\n\n",szBuffer);

    WSACleanup();
    return 0;

}

 

第23章 尝试互联网(4)【全书完】

标签:

原文地址:http://www.cnblogs.com/5iedu/p/4715321.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!