23.4 WinInet和FTP

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

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

(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下载文件    

第23章 尝试互联网(4)【全书完】_主机名_02                                             第23章 尝试互联网(4)【全书完】_句柄_03

软件运行时截图

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



/*------------------------------------------------------------
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结构体】

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

  ②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结构体中。

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

第23章 尝试互联网(4)【全书完】_主机名_06



#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;

}