�������� Linux Tags

23. ����Internet

Internet��ȫ�������͸����ͬЭ��������Ѷ�Ĵ��������壭���������¶����˸��˼���ļ���������Ȼ������Ѷ����͵����ʼ�ϵͳ��Internet���п���֮ǰ���Ѿ����ڣ�������ͨ�����������ģʽ�����Ҹ���û��������Ǹ��Էָ��ġ����磬ÿһ����Ѷ������Ҫ����ͬ�ĵ绰���룬�ò�ͬ��ʹ����ID�������¼��ÿһ�ֵ����ʼ�ϵͳ���������ض�ϵͳ�Ľɿ�ʹ����֮�䷢�ͺͽ����ʼ���

���ڣ�����ֻ��Ҫ����һ֧�绰�Ϳ�����������Internet�����ҿ��Ժ��е����ʼ�λַ���˽���ȫ��ͨ�š��ر�����World Wide Web�ϣ������֡�ͼ�κͶ�ý�壨�������������ֺ���Ѷ����ʹ���Ѿ���չ��������Ѷ�ķ�Χ�͹��ܡ�

���Ҫ�ṩ����Windows��������Internet��س�ʽ�������ij��׽��ܣ����ܻ���Ҫ�ټ��ϼ�����Ź������ԣ�����ʵ������Ҫ�����������С�͵�Microsoft WindowsӦ�ó�ʽ�ܹ���Ч�ش�Internet��ȡ����Ѷ��������������������ֱ���Windows Sockets (Winsock) API��Windows Internet��WinInet��API֧Ԯ�ĵ�������Э����FTP��File Transfer Protocol���IJ��֡�

Windows Sockets
��

Socket����University of California��Berkeley��У�����ĸ�������UNIX��ҵϵͳ��������·ͨѶ֧Ԯ�����↑����API���ڳ�Ϊ��Berkeley socket interface����

Sockets��TCP/IP
��

Socketͨ��������ר��춣�������Internetͨ�ŵĴ��������Э��/������·Э����TCP/IP��Transmission Control Protocol/Internet Protocol��ǣ����һ��������·Э����IP��Internet Protocol������ΪTCP/IP����ɲ���֮һ�����������ϴ���ɡ����Ϸ����datagram�����������Ϸ��������춱�ʶ������Դ��Ŀ�ĵصı�ͷ��Ѷ�����������Э����TCP��Transmission Control Protocol�����ṩ�˿ɿ��Ĵ���ͼ��IP���Ϸ����ȷ�Եķ�����

��TCP/IP�£�ͨѶ�˵���IPλַ�Ͳ��Ŷ��塣IPλַ����4��λԪ�飬���ȷ��Internet�ϵ��ŷ�����IPλַͨ�������ɵ�������ĸ�С�255�����֡��ĸ�ʽ��ʾ�����硸209.86.105.231��������ȷ�����ض��ķ�����ŷ����ṩ�ķ�������һЩ�����Ѿ���׼�������ṩ������֪�ķ���

��Socket��TCP/IP����ʱ��Socket����TCP/IP��ͨѶ�˵㡣��ˣ�Socketָ����IPλַ�Ͳ��š�

��·ʱ�����
��

��������ķ�����ʽ���ṩʱ��Э����Time Protocol����Internet�ŷ��������ᡣ�˳�ʽ�����Ŀǰ׼ȷ�����ں�ʱ�䣬���ô���Ѷ�趨����PCʱ�ӡ�

�����������ұ�׼�ͼ���Э�ᣨNational Institute of Standards and Technology������ǰ��Ϊ���ұ�׼�֣�National Bureau of Standards��������ά��׼ȷʱ�䣬��ʱ����������صĻ�������ϵ��׼ȷʱ���������ߵ�㲥���绰���롢���Բ��ŵ绰�����Լ�Internet�������Щ�������ļ���λ���վ http://www.bldrdoc.gov/timefreq ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½Æ¡ï¿½bldrdoc��ָ����Boulder��Colorado��NIST Time��λ�ú�Frequency Division����

����ֻ��NIST Network Time Service����Ȥ������ϸ���ļ�λ� http://www.bldrdoc.gov/timefreq/service/nts.htm ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½Ò³ï¿½Ð³ï¿½ï¿½ï¿½Ê®ï¿½ï¿½ï¿½á¹©NISTʱ�������ŷ��������磬��һ������Ϊtime-a.timefreq.bldrdoc.gov����IPλַΪ132.163.135.130��

����������д��һ��ʹ�÷�Internet NIST���Բ��ӷ���ij�ʽ��������춡�PC Magazine������Ҳ������Ziff-Davis����վ http://www.zdnet.com/pcmag/pctech/content/16/20/ut1620.001.html ï¿½ï¿½ï¿½Òµï¿½ï¿½ï¿½ï¿½Ë³ï¿½Ê½ï¿½ï¿½ï¿½ï¿½ï¿½Ñ§Ï°ï¿½ï¿½ï¿½Ê¹ï¿½ï¿½Windows Telephony API���˺��а�������

��Internet����������ͬ��ʱ�����ÿһ������Request for Comment��RFC������ΪInternet��׼������Э����Daytime Protocol����RFC-867���ṩ��һ��ASCII�ִ����ָ��׼ȷ�����ں�ʱ�䡣��ASCII�ִ���׼ȷ��ʽ������׼�������ǿ����������еĺ��塣ʱ��Э����RFC-868���ṩ��һ��32λԪ�����֣�������ʾ��1900��1��1���������������ʱ����UTC����������ĸ˳������ʾ����ʱ�����꣨Coordinated Universal Time���������������ν�ĸ������α�׼ʱ�䣨Greenwich Mean Time������GMT��Ӣ����������ʱ�䡣������Э����Ϊ��·ʱ��Э����Network Time Protocol����RFC-1305������Э���ܸ��ӡ�

������ǵ�Ŀ�ģ�����������Socket�Ͳ��ϸ���PCʱ�ӣ�ʱ��Э��RFC-868�Ѿ������ˡ�RFC-868ֻ��һ����ҳ�ļ���ļ�����Ҫ��˵��TCP���׼ȷʱ��ij�ʽӦ�������²��裺

  1. ���ᵽ�ṩ�˷�����ŷ�����37��
  2. ����32λԪ��ʱ�䡣
  3. �ر����ᡣ

���������Ѿ�֪���˱�д��ȡʱ������SocketӦ�ó�ʽ��ÿ��ϸ�ڡ�

NETTIME��ʽ
��

Windows Sockets API��ͨ��Ҳ��ΪWinSock����Berkeley Sockets API���ݣ���ˣ���������UNIX Socket��ʽ�����˳�����õ�Windows��ʹ�á�Windows�¸���һ����֧Ԯ�ɶ�Berkeley Socket����Ĺ����ṩ���亯ʽ����ʽ����WSA����WinSock API����Ϊ���ס���صĸ����Ͳο�λ�/Platform SDK/Networking and Distributed Services/Windows Sockets Version 2��

NETTIME�����ʽ23-1��ʾ��չʾ��ʹ��WinSock API�ķ�����

 ï¿½ï¿½Ê½23-1  NETTIME
NETTIME.C
/*----------------------------------------------------------------------------
   	NETTIME.C -- 	Sets System Clock from Internet Services
                						(c) Charles Petzold, 1998
-----------------------------------------------------------------------------*/

#include <windows.h>
#include "resource.h"

#define 	WM_SOCKET_NOTIFY (WM_USER + 1)
#define 	ID_TIMER         1

LRESULT 	CALLBACK WndProc   (HWND, UINT, WPARAM, LPARAM) ;
BOOL    		CALLBACK MainDlg   (HWND, UINT, WPARAM, LPARAM) ;
BOOL    		CALLBACK ServerDlg 		(HWND, UINT, WPARAM, LPARAM) ;

void 	ChangeSystemTime		(HWND hwndEdit, ULONG ulTime) ;
void 	FormatUpdatedTime		(HWND hwndEdit, SYSTEMTIME * pstOld, 
                                SYSTEMTIME * pstNew) ;
void EditPrintf (HWND hwndEdit, TCHAR * szFormat, ...) ;
HINSTANCE hInst ;
HWND      		hwndModeless ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     	static TCHAR 	szAppName[] = TEXT ("NetTime") ;
     	HWND         			hwnd ;
     	MSG          			msg ;
     	RECT         			rect ;
     	WNDCLASS     			wndclass ;

     	hInst = hInstance ;
     	wndclass.style         			= 0 ;
     	wndclass.lpfnWndProc   			= WndProc ;
     	wndclass.cbClsExtra    			= 0 ;
     	wndclass.cbWndExtra    			= 0 ;
     	wndclass.hInstance     			= hInstance ;
     	wndclass.hIcon         			= LoadIcon (NULL, IDI_APPLICATION) ;
     	wndclass.hCursor       			= NULL ;
     	wndclass.hbrBackground 		= NULL ;
     	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, TEXT ("Set System Clock from Internet"),
                          	WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
                            WS_BORDER | WS_MINIMIZEBOX,
           					CW_USEDEFAULT, CW_USEDEFAULT,
                          	CW_USEDEFAULT, CW_USEDEFAULT,
                          	NULL, NULL, hInstance, NULL) ;

         	// Create the modeless dialog box to go on top of the window
     	hwndModeless = CreateDialog (hInstance, szAppName, hwnd, MainDlg) ;
          	// Size the main parent window to the size of the dialog box.  
          	//   Show both windows.

     	GetWindowRect (hwndModeless, &rect) ;
     	AdjustWindowRect (&rect, WS_CAPTION | WS_BORDER, FALSE) ;

     	SetWindowPos (	hwnd, NULL, 0, 0, rect.right - rect.left,
                   		rect.bottom - rect.top, SWP_NOMOVE) ;

     	ShowWindow (hwndModeless, SW_SHOW) ;     
     	ShowWindow (hwnd, iCmdShow) ;
     	UpdateWindow (hwnd) ;

      	// Normal message loop when a modeless dialog box is used.
     	while (GetMessage (&msg, NULL, 0, 0))
     	{
          		if (hwndModeless == 0 || !IsDialogMessage (hwndModeless, &msg))
          		{
               			TranslateMessage (&msg) ;
               			DispatchMessage (&msg) ;
          		}
     	}
     	return msg.wParam ;
}

LRESULT CALLBACK WndProc (	HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     	switch (message)
     {
     	case 	WM_SETFOCUS:
          			SetFocus (hwndModeless) ;
          			return 0 ;

     	case 	WM_DESTROY:
          			PostQuitMessage (0) ;
          			return 0 ;
     }
     	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

BOOL CALLBACK MainDlg (	HWND hwnd, UINT message, WPARAM wParam, 
									LPARAM lParam)
{
     	static char   		szIPAddr[32] = { "132.163.135.130" } ;
     	static HWND   		hwndButton, hwndEdit ;
     	static SOCKET 		sock ;
     	static struct 		sockaddr_in sa ;
     	static TCHAR  		szOKLabel[32] ;
     	int           					iError, iSize ;
     	unsigned long 		ulTime ;
     	WORD          					wEvent, wError ;
     	WSADATA       				WSAData ;     
 
     	switch (message)
     	{
     	case 	WM_INITDIALOG:
          			hwndButton = GetDlgItem (hwnd, IDOK) ;
          			hwndEdit = GetDlgItem (hwnd, IDC_TEXTOUT) ;
          			return TRUE ;

     	case 	WM_COMMAND:
          			switch (LOWORD (wParam))
          		{
          			case 	IDC_SERVER:
               		DialogBoxParam (hInst, TEXT ("Servers"), hwnd, ServerDlg, (LPARAM) szIPAddr) ;
               		return TRUE ;

          			case 	IDOK:
                    // Call "WSAStartup" and display description text

               		if (iError = WSAStartup (MAKEWORD(2,0), &WSAData))
               		{
                    EditPrintf (hwndEdit, TEXT ("Startup error #%i.\r\n"), iError) ;
                    return TRUE ;
               			}
               		EditPrintf (hwndEdit, TEXT ("Started up %hs\r\n"), 
                                WSAData.szDescription);

                    // Call "socket"

               					sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ;

               					if (sock == INVALID_SOCKET)
               					{
                    EditPrintf (hwndEdit, TEXT ("Socket creation error #%i.\r\n"), WSAGetLastError ()) ;
                 WSACleanup () ;
                 return TRUE ;
               	}
               EditPrintf (hwndEdit, TEXT ("Socket %i created.\r\n"), sock) ;

              // Call "WSAAsyncSelect" 

              if (SOCKET_ERROR == WSAAsyncSelect (sock, hwnd, WM_SOCKET_NOTIFY, FD_CONNECT | FD_READ))
               					{
              EditPrintf (	hwndEdit, TEXT ("WSAAsyncSelect error #%i.\r\n"), WSAGetLastError ()) ;
                 closesocket (sock) ;
                 WSACleanup () ;
                 return TRUE ;
               	}

                 // Call "connect" with IP address and time-server port

               	sa.sin_family           = AF_INET ;
               	sa.sin_port             = htons (IPPORT_TIMESERVER) ; 
               	sa.sin_addr.S_un.S_addr = inet_addr (szIPAddr) ;

               	connect(sock, (SOCKADDR *) &sa, sizeof (sa)) ;

               // "connect" will return SOCKET_ERROR because even if it
               // succeeds, it will require blocking. The following only
               // reports unexpected errors.

               if (WSAEWOULDBLOCK != (iError = WSAGetLastError ()))
               	{
               EditPrintf (hwndEdit, TEXT ("Connect error #%i.\r\n"), iError) ;
                    		closesocket (sock) ;
                    		WSACleanup () ;
                    		return TRUE ;
               }
               EditPrintf (hwndEdit, TEXT ("Connecting to %hs..."), szIPAddr) ;
     
               // The result of the "connect" call will be reported 
               // through the WM_SOCKET_NOTIFY message.
               // Set timer and change the button to "Cancel"

              SetTimer (hwnd, ID_TIMER, 1000, NULL) ;
              GetWindowText (hwndButton, szOKLabel, sizeof (szOKLabel) /sizeof (TCHAR)) ;
              SetWindowText (hwndButton, TEXT ("Cancel")) ;
              SetWindowLong (hwndButton, GWL_ID, IDCANCEL) ;
             return TRUE ;

       			case 	IDCANCEL:
               					closesocket (sock) ;
               					sock = 0 ;
               					WSACleanup () ;
               					SetWindowText (hwndButton, szOKLabel) ;
               					SetWindowLong (hwndButton, GWL_ID, IDOK) ;

               					KillTimer (hwnd, ID_TIMER) ;
               					EditPrintf (hwndEdit, TEXT ("\r\nSocket closed.\r\n")) ;
               					return TRUE ;

          			case 	IDC_CLOSE:
         					if (sock)
                    		SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ;

               					DestroyWindow (GetParent (hwnd)) ;
               					return TRUE ;
          			}
          			return FALSE ;

     	case 	WM_TIMER:
          			EditPrintf (hwndEdit, TEXT (".")) ;
          			return TRUE ;

     	case 	WM_SOCKET_NOTIFY:
          			wEvent = WSAGETSELECTEVENT (lParam) ;   // ie, LOWORD
          			wError = WSAGETSELECTERROR (lParam) ;   // ie, HIWORD

               				// Process two events specified in WSAAsyncSelect

          			switch (wEvent)
          			{
        // This event occurs as a result of the "connect" call

          			case 	FD_CONNECT:
               					EditPrintf (hwndEdit, TEXT ("\r\n")) ;

               					if (wError)
               					{
       EditPrintf (	hwndEdit, TEXT ("Connect error #%i."), wError) ;
       SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ;
      return TRUE ;
           }
        EditPrintf (hwndEdit, TEXT ("Connected to %hs.\r\n"), szIPAddr) ;

         // Try to receive data. The call will generate an error
         // of WSAEWOULDBLOCK and an event of FD_READ

         recv (sock, (char *) &ulTime, 4, MSG_PEEK) ;
         EditPrintf (hwndEdit, TEXT ("Waiting to receive...")) ;
         return TRUE ;

         // This even occurs when the "recv" call can be made
               
			case 	FD_READ:
               					KillTimer (hwnd, ID_TIMER) ;
               					EditPrintf (hwndEdit, TEXT ("\r\n")) ;

               					if (wError)
               					{
        EditPrintf (hwndEdit, TEXT ("FD_READ error #%i."), wError) ;
        SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ;
        return TRUE ;
        }
                    					// Get the time and swap the bytes

          iSize = recv (sock, (char *) &ulTime, 4, 0) ;
          ulTime = ntohl (ulTime) ;
          EditPrintf (hwndEdit, 
          TEXT ("Received current time of %u seconds ")
          TEXT ("since Jan. 1 1900.\r\n"), ulTime) ;

          // Change the system time
     
               					ChangeSystemTime (hwndEdit, ulTime) ;
               					SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ;
               					return TRUE ;
          			}
          			return FALSE ;
     	}
     	return FALSE ;
}

BOOL CALLBACK ServerDlg (	HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     	static char * 	szServer ;
     	static WORD   		wServer = IDC_SERVER1 ;
     	char          					szLabel [64] ;

     	switch (message)
     	{
     	case 	WM_INITDIALOG:
          			szServer = (char *) lParam ;
          			CheckRadioButton (hwnd, IDC_SERVER1, IDC_SERVER10, wServer) ;
          			return TRUE ;

     	case 	WM_COMMAND:
          			switch (LOWORD (wParam))
          			{
          			case 	IDC_SERVER1:
          			case 	IDC_SERVER2:
          			case 	IDC_SERVER3:
          			case 	IDC_SERVER4:
          			case 	IDC_SERVER5:
          			case 	IDC_SERVER6:
          			case 	IDC_SERVER7:
          			case 	IDC_SERVER8:
          			case 	IDC_SERVER9:
          			case 	IDC_SERVER10:
               					wServer = LOWORD (wParam) ;
               					return TRUE ;

          			case 	IDOK:
               					GetDlgItemTextA (hwnd, wServer, szLabel, sizeof (szLabel)) ;
               					strtok (szLabel, "(") ;
               					strcpy (szServer, strtok (NULL, ")")) ;
               					EndDialog (hwnd, TRUE) ;
               					return TRUE ;

          			case 	IDCANCEL:
               					EndDialog (hwnd, FALSE) ;
               					return TRUE ;
          			}
          			break ;
    	}
     	return FALSE ;
}

void ChangeSystemTime (HWND hwndEdit, ULONG ulTime)
{
     	FILETIME      				ftNew ;
     	LARGE_INTEGER 		li ;
     	SYSTEMTIME    			stOld, stNew ;

     	GetLocalTime (&stOld) ;
     	stNew.wYear         						= 1900 ;
     	stNew.wMonth        					= 1 ;
     	stNew.wDay          					= 1 ;
     	stNew.wHour         					= 0 ;
     	stNew.wMinute       					= 0 ;
     	stNew.wSecond       					= 0 ;
     	stNew.wMilliseconds 			= 0 ;

     	SystemTimeToFileTime (&stNew, &ftNew) ;
     	li = * (LARGE_INTEGER *) &ftNew ;
     	li.QuadPart += (LONGLONG) 10000000 * ulTime ; 
     	ftNew = * (FILETIME *) &li ;
     	FileTimeToSystemTime (&ftNew, &stNew) ;

     	if (SetSystemTime (&stNew))
     	{
          		GetLocalTime (&stNew) ;
          		FormatUpdatedTime (hwndEdit, &stOld, &stNew) ;
 	}
     	else
          		EditPrintf (hwndEdit, TEXT ("Could NOT set new date and time.")) ;
}

void FormatUpdatedTime (	HWND hwndEdit, SYSTEMTIME * pstOld, SYSTEMTIME * pstNew)
{
     	TCHAR szDateOld [64], szTimeOld [64], szDateNew [64], szTimeNew [64] ;
     	GetDateFormat (LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE | DATE_SHORTDATE,
                    						pstOld, NULL, szDateOld, sizeof (szDateOld)) ;
     	GetTimeFormat (	LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE | 
                        TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
                    	pstOld, NULL, szTimeOld, sizeof (szTimeOld)) ;

     	GetDateFormat (LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE | DATE_SHORTDATE,
                    	pstNew, NULL, szDateNew, sizeof (szDateNew)) ;
     	GetTimeFormat (	LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE | 
                        TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
                    	pstNew, NULL, szTimeNew, sizeof (szTimeNew)) ;

     	EditPrintf (hwndEdit, TEXT ("System date and time successfully changed ")
                 			 TEXT ("from\r\n\t%s, %s.%03i to\r\n\t%s, %s.%03i."), 
                 	szDateOld, szTimeOld, pstOld->wMilliseconds,
                 	szDateNew, szTimeNew, pstNew->wMilliseconds) ;
}

void EditPrintf (HWND hwndEdit, TCHAR * szFormat, ...)
{
     	TCHAR 		szBuffer [1024] ;
     	va_list	pArgList ;

     	va_start (pArgList, szFormat) ;
     	wvsprintf (szBuffer, szFormat, pArgList) ;
     	va_end (pArgList) ;
     	SendMessage (hwndEdit, EM_SETSEL, (WPARAM) -1, (LPARAM) -1) ;
     	SendMessage (hwndEdit, EM_REPLACESEL, FALSE, (LPARAM) szBuffer) ;
     	SendMessage (hwn dEdit, EM_SCROLLCARET, 0, 0) ;
}
 NETTIME.RC ��ժ¼��
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
// Dialog
SERVERS DIALOG DISCARDABLE  20, 20, 274, 202
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "NIST Time Service Servers"
FONT 8, "MS Sans Serif"
BEGIN
    	DEFPUSHBUTTON   		"OK",IDOK,73,181,50,14
    	PUSHBUTTON      			"Cancel",IDCANCEL,150,181,50,14
    	CONTROL         
        		"time-a.timefreq.bldrdoc.gov (132.163.135.130) NIST, Boulder, Colorado",
              		IDC_SERVER1,"Button",BS_AUTORADIOBUTTON,9,7,256,16
    	CONTROL         
  		"time-b.timefreq.bldrdoc.gov (132.163.135.131) NIST, Boulder, Colorado",
            		IDC_SERVER2,"Button",BS_AUTORADIOBUTTON,9,24,256,16
    	CONTROL         
          		"time-c.timefreq.bldrdoc.gov (132.163.135.132) Boulder, Colorado",
                 		IDC_SERVER3,"Button",BS_AUTORADIOBUTTON,9,41,256,16
    	CONTROL         
        		"utcnist.colorado.edu (128.138.140.44) University of Colorado, Boulder",
              		IDC_SERVER4,"Button",BS_AUTORADIOBUTTON,9,58,256,16
    	CONTROL         
                 		"time.nist.gov (192.43.244.18) NCAR, Boulder, Colorado",
             		IDC_SERVER5,"Button",BS_AUTORADIOBUTTON,9,75,256,16
    	CONTROL         
                   		"time-a.nist.gov (129.6.16.35) NIST, Gaithersburg, Maryland",
                    		IDC_SERVER6,"Button",BS_AUTORADIOBUTTON,9,92,256,16
    	CONTROL         
                   		"time-b.nist.gov (129.6.16.36) NIST, Gaithersburg, Maryland",
                    		IDC_SERVER7,"Button",BS_AUTORADIOBUTTON,9,109,256,16
    	CONTROL         
               		"time-nw.nist.gov (131.107.1.10) Microsoft, Redmond, Washington",
                    		IDC_SERVER8,"Button",BS_AUTORADIOBUTTON,9,126,256,16
    	CONTROL         
                 		"utcnist.reston.mci.net (204.70.131.13) MCI, Reston, Virginia",
                    		IDC_SERVER9,"Button",BS_AUTORADIOBUTTON,9,143,256,16

    	CONTROL         
                      		"nist1.data.com (209.0.72.7) Datum, San Jose, California",
                    		IDC_SERVER10,"Button",BS_AUTORADIOBUTTON,9,160,256,16
END
NETTIME DIALOG DISCARDABLE  0, 0, 270, 150 STYLE WS_CHILD FONT 8, "MS Sans Serif"
BEGIN
    	DEFPUSHBUTTON   		"Set Correct Time",IDOK,95,129,80,14
    	PUSHBUTTON      			"Close",IDC_CLOSE,183,129,80,14
    	PUSHBUTTON      			"Select Server...",IDC_SERVER,7,129,80,14
    	EDITTEXT        				IDC_TEXTOUT,7,7,253,110,ES_MULTILINE | ES_AUTOVSCROLL | 
                    							ES_READONLY | WS_VSCROLL | NOT WS_TABSTOP
END
 RESOURCE.H ��ժ¼��
// Microsoft Developer Studio generated include file.
// Used by NetTime.rc

#define 		IDC_TEXTOUT                     					101
#define 		IDC_SERVER1                     					1001
#define 		IDC_SERVER2                     					1002
#define 		IDC_SERVER3                     					1003
#define 		IDC_SERVER4                     					1004
#define 		IDC_SERVER5                     					1005
#define 		IDC_SERVER6                     					1006
#define 		IDC_SERVER7                     					1007
#define 		IDC_SERVER8                     					1008
#define 		IDC_SERVER9                     					1009
#define 		IDC_SERVER10                    					1010
#define 		IDC_SERVER                      					1011
#define 		IDC_CLOSE          								    1012

�ڽṹ�ϣ�NETTIME��ʽ������һ������NETTIME.RC�е�NETTIME�������ķ�ϵͳģ̬�Ի����顣��ʽ���¶������Ӵ��ijߴ磬�Ա��ϵͳģ̬�Ի�������Ը��dz�ʽ�������Ӵ���ʾ���򡣶Ի��������һ��Ψ���༭������ʽ���д��������Ѷ����һ����Select Server����ť��һ����Set Correct Time����ť��һ����Close����ť����Close����ť�����ֹ��ʽ��

MainDlg�е�szIPAddr������춴����ŷ���λַ���ڶ����ִ���132.163.135.130������Select Server����ť��������NETTIME.RC�е�SERVERSģ�彨���ĶԻ����顣szIPAddr������Ϊ����һ���������ݸ�DialogBoxParam����Server���Ի������г���10���ŷ��������Ǵ�NIST��վ�����ָ������ģ�����Щ�ŷ����ṩ�����Ǹ���Ȥ�ķ��񡣵�ʹ���ߵ���һ���ŷ���ʱ��ServerDlg��������ť���֣��Ի����Ӧ��IPλַ����λַ������szIPAddr�����С�

��ʹ���߰��¡�Set Correct Time����ťʱ����ť������һ��WM_COMMANDѶϢ������wParam�ĵ�������IDOK��MainDlg�е�IDOK�����Ǵ󲿷�Socket��ʼ��Ϊ�����ĵط���

ʹ��Windows Sockets APIʱ���κ�Windows��ʽ������еĵ�һ����ʽ�ǣ�

iError = WSAStartup (wVersion, &WSAData) ;

NETTIME����һ�������趨Ϊ0x0200����ʾ2.0�汾��������ʱ��WSAData�ṹ������Windows Socketsʵ���������Ѷ������NETTIME����ʾszDescription�ִ�������Ҫ�ṩ��һЩ�汾��Ѷ��

Ȼ�ᣬNETTIME���º���socket��ʽ��

sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ;

��һ��������һ��λַ���࣬��ʾ�˴���ij��Internetλַ���ڶ���������ʾ����������������ʽ���أ������������Ϸ������ʽ���أ�������Ҫ������ֻ��4��λԪ�鳤�������Ϸ������춽ϴ�����Ͽ飩������һ��������һ��Э��������ָ��ʹ�õ�InternetЭ����TCP������RFC-868�����������Э��֮һ��socket��ʽ�Ĵ���ֵ������SOCKET��̬�ı����У��Ա������Socket��ʽ�ĺ��С�

NETTIME������е�WSAAsynchSelect����һ��Windows���е�Socket��ʽ���˺�ʽ��춱�����Internet��Ӧ���������Ӧ�ó�ʽ��ס����WinSock�ļ��У���Щ��ʽ�롸�谭�ԣ�blocking�����йء�Ҳ����˵�����Dz��ܱ�֤�����ѿ�����Ȩ���ظ���ʽ��WSAAsyncSelect��ʽǿ���谭�Եĺ�ʽתΪ���谭�Եģ����ں�ʽִ����֮ǰ�ѿ�����ظ���ʽ����ʽ�Ľ����ѶϢ����ʽ�����Ӧ�ó�ʽ��WSAAsyncSelect��ʽ��Ӧ�ó�ʽָ��ѶϢ�ͽ���ѶϢ���Ӵ�����ֵ��ͨ������ʽ���﷨���£�

WSAAsyncSelect (sock, hwnd, message, iConditions) ;

Ϊ������NETTIMEʹ�ó�ʽ�����һ��ѶϢ����ѶϢ��ΪWM_SOCKET_NOTIFY����Ҳ��WSAAsyncSelect������һ��������ָ��ѶϢ���͵��������ر�������ͽ�������ʱ��FD_CONNECT | FD_READ����

NETTIME���е���һ��WinSock��ʽ��connect���˺�ʽ��Ҫһ��ָ��Socketλַ�ṹ��ָ�꣬��춲�ͬ��Э����˵����Socketλַ�ṹ�Dz�ͬ�ġ�NETTIMEʹ��ΪTCP/IP��ƵĽṹ�汾��

struct sockaddr_in 
{
     	short          					sin_family;
     	u_short        				sin_port;
     	struct in_addr 	sin_addr;
     	char           					sin_zero[8];
} ;

����in_addr�����ָ��Internetλַ����������4��λԪ�飬����2���������Ŷ�����������1���������ų���������ʾ��

NETTIME��sin_family��λ�趨ΪAF_INET����춱�ʾλַ���ࡣ��sin_port�趨Ϊ���ţ�������ʱ��Э���IJ��ţ�RFC-868��ʾΪ37������Ҫ�������ʱ������������λ��Ϊ37�������������ͨ��Internetʱ���ṹ�����������λ�����ǡ�big endian���ģ�����ߵ�λԪ���ŵ�һ����Intel΢��������little endian�����˵��ǣ�htons����host-to-network short������ʽʹλԪ�鷭ת�����NETTIME��sockaddr_in�ṹ��sin_port��λ�趨Ϊ��

htons (IPPORT_TIMESERVER)

WINSOCK2.H�н���������Ϊ37��NETTIME��inet_addr��ʽ��������szIPAddr�ִ��е��ŷ���λַת��Ϊ�������ų�����������������趨�ṹ��sin_addr��λ��

���Ӧ�ó�ʽ��Windows 98�º���connect������ĿǰWindowsû�����ᵽInternet����ô����ʾ���������ߡ��Ի����顣�������ν�ġ��Զ����š�����Windows NT 4.0��û��ʵ�����Զ����š�����������NT������ִ�У���ô��ִ��NETTIME֮ǰ���ͱ�����������Internet��

connect��ʽͨ���Ѿ����谭�������ʽ��ִ�У�������Ϊ����ɹ���ǰ��Ҫ��Щʱ�䡣Ȼ�������NETTIME������WSAAsyncSelect������connect����ȴ����ᣬ��ʵ�ϣ�������������SOCKET_ERROR��ֵ���Ⲣ���dz����˴�����ֻ�DZ�ʾ���ڻ�û�����߳ɹ����ѡ�NETTIMEҲ�������������ֵ��ֻ�Ǻ���WSAGetLastError���ѡ����WSAGetLastError����WSAEWOULDBLOCK������ʽ��ִ��ͨ��Ҫ���裬�����ﲢû�����裩���Ǿ�һ�ж�����������NETTIME����Set Correct Time����ť�ijɡ�Cancel�������趨��һ��1��ļ�ʱ����WM_TIMER�Ĵ�����ʽֻ���ڳ�ʽ�Ӵ�����ʾ��㣬�Ը���ʹ���߳�ʽ����ִ�У�ϵͳû�е�����

�����������ʱ��MainDlg��WM_SOCKET_NOTIFYѶϢ��NETTIME��WSAAsyncSelect��ʽ��ָ���ij�ʽ�Զ�ѶϢ��֪ͨ��lParam�ĵ�������FD_CONNECT���������ʾ������ʱ�Ĵ�������dz�ʽ�������ᵽָ�����ŷ�����NETTIME���г�������9���ŷ���������ѡ���������������������ŷ�����

���һ��˳������ôNETTIME������recv����receive�����ա�����ʽ����ȡ���ϣ�

recv (sock, (char *) &ulTime, 4, MSG_PEEK) ;

����ζ������4��λԪ��������ulTime����������һ��������ʾֻ�Ƕ������ϣ��������������������ɾ������connect��ʽһ����recv����һ��������룬�Ա�ʾ��ʽͨ�����裬����ʱû�����衣��������˵����Ȼ�ⲻ����ܣ�����ʽ�����ܴ������ϵ�һ���֣�Ȼ��͸���ٴκ����Ի�������32��λԪ��ֵ���Ǿ��Ǻ���recv��ʽʱ����MSG_PEEKѡ���ԭ��

��connect��ʽ���ƣ�recv��ʽҲ����WM_SOCKET_NOTIFYѶϢ����ʱ����FD_READ���¼����롣NETTIMEͨ���ٴκ���recv���Դ˻�Ӧ����ʱ����IJ�����0����춴�������ɾ�����ϡ��ҽ���Ҫ����һ�³�ʽ�������յ���ulTime�ķ�����ע�⣬NETTIMEͨ�����Լ�����WM_COMMANDѶϢ��������������ѶϢ��wParam���IDCANCEL���Ի��������ͨ������closesocket��WSACleanup����Ӧ��

�ٴκ���NETTIME���յ�32λԪ��ulTimeֵ�Ǵ�1990��1��1�տ�ʼ��0:00 UTC�����������˳���λԪ���ǵ�һ��λԪ�飬��˸�ֵ����ͨ��ntohl����network-to-host long������ʽ����������λԪ��˳���Ա�Intel΢�������ܹ�������Ȼ�ᣬNETTIME����ChangeSystemTime��ʽ��

ChangeSystemTime����ȡ��Ŀǰ�ı���ʱ�䣭����ʹ��������ʱ�����չ��Լʱ���Ŀǰϵͳʱ�䡣��SYSTEMTIME�ṹ�趨Ϊ1900��1��1����ҹ��0ʱ�����������SYSTEMTIME�ṹ���ݸ�SystemTimeToFileTime�����˽ṹת��ΪFILETIME�ṹ��FILETIMEʵ����ֻ��������32λԪ��DWORDһ�����64λԪ��������������ʾ��1601��1��1��������Ϊ100���루nanosecond���ļ������

ChangeSystemTime��ʽ��FILETIME�ṹת��ΪLARGE_INTEGER������һ��union������64λԪ��ֵ���Ա���������32λԪ��ֵʹ�ã����ߵ���һ��__int64������̬��64λԪ����ʹ�ã�__int64������̬��Microsoft��������ANSI C��׼�����䣩����ˣ���ֵ��1601��1��1�յ�1900��1��1��֮����Ϊ100����ļ���������������1900��1��1��������Ϊ100����ļ������ulTime��10,000,000����

Ȼ��ͨ������FileTimeToSystemTime����Ϊ�����FILETIMEֵת����SYSTEMTIME�ṹ����Ϊʱ��Э������Ŀǰ��UTCʱ�䣬����NETTIMEͨ������SetSystemTime���趨ʱ�䣬SetSystemTimeҲ����UTC�������ʾ��Ŀ�ģ���ʽ����GetLocalTime����ø���ʱ�䡣����ı���ʱ����µı���ʱ��һ�𴫵ݸ�FormatUpdatedTime�������ʽ��GetTimeFormat��ʽ��GetDateFormat��ʽ��ʱ��ת��ΪASCII�ִ���

�����ʽ��Windows NT��ִ�У�����ʹ����û��ȡ���趨ʱ�������Ȩ����ôSetSystemTime��ʽ����ʧ�ܡ����SetSystemTimeʧ�ܣ���NETTIME������һ����ʱ��δ�趨�ɹ���ѶϢ��ָ���������ڡ�

WININET��FTP
��

WinInet����Windows Internet����API��һ���߽׺�ʽ����������ʽд����ʹ������������InternetЭ����������Э���ǣ����World Wide Webȫ����Ѷ���ij����ִ���Э����HTTP��Hypertext Transfer Protocol������������Э����FTP��File Transfer Protocol������һ����ΪGopher�ĵ�������Э����WinInet��ʽ���﷨�볣�õ�Windows������ʽ���﷨���ƣ���ʹ��ʹ����ЩЭ������ʹ�ñ��شŵ����ϵĵ���һ�����ס�WinInet API���ļ�λ�/Platform SDK/Internet, Intranet, Extranet Services/Internet Tools and Technologies/WinInet API��

����ķ�����ʽ��չʾ���ʹ��WinInet API��FTP���֡���������վ�Ĺ�˾Ҳ���С�����FTP���ŷ���������ʹ���߿����ڲ�����ʹ�������ƺ��������������ص��������磬�������Internet Explorer��λַ������ ftp://ftp.microsoft.com ï¿½ï¿½ï¿½ï¿½Ã´ï¿½ï¿½ï¿½Í¿ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½FTP�ŷ����ϵ�Ŀ¼�����ص������������ftp://ftp.cpetzold.com/cpetzold.com/ProgWin/UpdDemo����ô�������ҵ�����FTP�ŷ����Ϸ��������Ҫ�ᵽ�ķ�����ʽһ��ʹ�õĵ����б���

��Ȼ�ֽ�FTP����Դ������Webʹ������˵��������ô����ʹ�ã�������Ȼ�൱���á����磬Ӧ�ó�ʽ������FTP������FTP�ŷ�����ȡ�����ϣ���Щȡ�����ϵ��������򼸺���ȫ��̨���´�����������Ҫʹ���߲��ġ���������ǽ����۵�UPDDEMO����update demonstration�����·���������ʽ�Ĺ��롣

FTP API�ſ�
��

ʹ��WinInet�ij�ʽ���������к���WinInet��ʽ��ԭʼ�����а�����ͷ����WININET.H����ʽ����������WININET.LIB����Microsoft Visual C++�У��������ڡ�Project Settings���Ի�����ġ�Link��ҳ���ǩ��ָ����ִ��ʱ����ʽ����WININET.DLL��̬�����ʽ�����ᡣ

������������У��Ҳ�����ϸ���ۺ�ʽ���﷨����ΪijЩ��ʽ�кܶ�ѡ�����������൱���ӡ�Ҫ����WinInet�������Խ�UPDDEMOԭʼ�뵱��ʳ������������ʱ����Ҫ�����˽��йصĸ��������Լ�FTP��ʽ�ķ�Χ��

Ҫʹ��Windows Internet API������Ҫ����InternetOpen��Ȼ�ᣬʹ��WinInet֧Ԯ���κ�һ��Э����InternetOpen����һ��Internet��ҵ���ţ������浽HINTERNET��̬�ı����С�����WinInet API���ᣬӦ��ͨ������InternetCloseHandle���رմ��š�

Ҫʹ��FTP������������Ҫ����InternetConnect���˺�ʽ��Ҫʹ����InternetOpen����Internet��ҵ���ţ����Ҵ���FTP��ҵ�Ĵ��š����ɽ��˴�����Ϊ���ƿ�ͷΪFtp�����к�ʽ�ĵ�һ��������InternetConnect��ʽ�IJ���ָ��Ҫʹ�õ�FTP�����ṩ���ŷ������ƣ����磬ftp.cpetzold.com���˺�ʽ����Ҫʹ�������ƺ����롣�����ȡ����FTP�ŷ�������Щ���������趨ΪNULL�����Ӧ�ó�ʽ����InternetConnectʱPC��û�����ᵽInternet��Windows 98����ʾ���������ߡ��Ի����顣��ʹ��FTP��Ӧ�ó�ʽ����ʱ������InternetCloseHandle���رմ��š�

��ʱ���Կ�ʼ������Ftp���׵ĺ�ʽ������������Щ��ʽ���׼��Windows����I/O��ʽ�����ơ�Ϊ�˱���������Э���ظ���һЩ��InternetΪ���׵ĺ�ʽҲ���Դ���FTP��

�����ĸ���ʽ��춴���Ŀ¼��

fSuccess = FtpCreateDirectory 		(hFtpSession,	szDirectory) ;
fSuccess = FtpRemoveDirectory 		(hFtpSession,	szDirectory) ;
fSuccess = FtpSetCurrentDirectory 	(hFtpSession,	szDirectory) ;
fSuccess = FtpGetCurrentDirectory 	(hFtpSession,	szDirectory, &dwCharacterCount) ;

ע�⣬��Щ��ʽ������������Ϥ��Windows�ṩ��춴������ص���ϵͳ��CreateDirectory��RemoveDirectory��SetCurrentDirectory��GetCurrentDirectory��ʽ��

��Ȼ����ȡ����FTP��Ӧ�ó�ʽ���ܽ�����ɾ��Ŀ¼�����ң���ʽҲ���ܼٶ�FTPĿ¼���к�Windows����ϵͳ��ͬ��Ŀ¼�ṹ��̬���ر��������·�����趨Ŀ¼�ij�ʽ�����ܼٶ�����µ�Ŀ¼ȫ����һ�С������ʽ��Ҫ֪����������Ŀ¼���������ƣ���ô������SetCurrentDirectory֮������ٺ���GetCurrentDirectory��GetCurrentDirectory���ִ��������ٰ���MAX_PATH��Ԫ����������һ������Ӧָ�������ֵ�ı�����

����������ʽ����ɾ��������������������������������FTP�ŷ����ϣ���

fSuccess = FtpDeleteFile (hFtpSession, szFileName) ;
fSuccess = FtpRenameFile (hFtpSession, szOldName, szNewName) ;

�����Ⱥ���FtpFindFirstFile�����Բ��ҵ��������뺬��������Ԫ�ĵ�����ʽ����Ķ�����������˺�ʽ����FindFirstFile��ʽ��������ʹ������ͬ��WIN32_FIND_DATA�ṹ���õ���Ϊ�оٳ����ĵ���������һ�����š������Խ��˴��Ŵ��ݸ�InternetFindNextFile��ʽ�Ի�ö���ĵ���������Ѷ������ͨ������InternetCloseHandle���رմ��š�

Ҫ�򿪵��������Ժ���FtpFileOpen�������ʽ����һ���������ţ��˴��ſ������InternetReadFile��InternetReadFileEx��InternetWrite��InternetSetFilePointer���С��������ͨ��������õ�InternetCloseHandle��ʽ���رմ��š�

���ᣬ���������߼���ʽ�ر����ã�FtpGetFile���н�������FTP�ŷ������Ƶ����ؼ����壬���ϲ���FtpFileOpen��FileCreate��InternetReadFile��WriteFile��InternetCloseHandle��CloseHandle���С�FtpGetFile����һ��������һ����꣬��������Ѿ�����ͬ����������ô����꽫���º�ʽ����ʧ�ܡ�FtpPutFile��˺�ʽ���ƣ���춽������ӱ��ؼ����帴�Ƶ�FTP�ŷ�����

����չʾ��ʽ
��

UPDDEMO�����ʽ23-2��ʾ��չʾ����WinInet FTP��ʽ�ڵڶ���ִ����ִ���ڼ������FTP�ŷ��������ص����ķ�����

 ï¿½ï¿½Ê½23-2  UPDDEMO
UPDDEMO.C
/*---------------------------------------------------------------------------
   	UPDDEMO.C -- Demonstrates Anonymous FTP Access
                						(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/

#include 		<windows.h>
#include 		<wininet.h>
#include 		<process.h>
#include 		"resource.h"

     		// User-defined messages used in WndProc

#define 	WM_USER_CHECKFILES	(WM_USER + 1)
#define 	WM_USER_GETFILES   		(WM_USER + 2)

     		// Information for FTP download

#define 	FTPSERVER 	TEXT 	("ftp.cpetzold.com")
#define 	DIRECTORY 	TEXT 	("cpetzold.com/ProgWin/UpdDemo")
#define 	TEMPLATE  	TEXT 	("UD??????.TXT")

     // Structures used for storing filenames and contents
typedef struct
{
     	TCHAR * szFilename ;
     	char  * szContents ;
}
FILEINFO ;
typedef struct
{
     	int      			iNum ;
     	FILEINFO 		info[1] ;
}
FILELIST ;
     // Structure used for second thread
typedef struct
{
     	BOOL bContinue ;
     	HWND hwnd ;
}
PARAMS ;
     		// Declarations of all functions in program
LRESULT 	CALLBACK 		WndProc (HWND, UINT, WPARAM, LPARAM) ;
BOOL    		CALLBACK 		DlgProc (HWND, UINT, WPARAM, LPARAM) ;
VOID             						FtpThread (PVOID) ;
VOID             						ButtonSwitch (HWND, HWND, TCHAR *) ;
FILELIST *       				GetFileList (VOID) ;
int              						Compare (const FILEINFO *, const FILEINFO *) ;

     		// A couple globals

HINSTANCE hInst ;
TCHAR     			szAppName[] = TEXT ("UpdDemo") ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    							PSTR szCmdLine, int iCmdShow)
{
     	HWND         					hwnd ;
     	MSG          					msg ;
     	WNDCLASS     				wndclass ;

     	hInst = hInstance ;
     	wndclass.style         			= 0 ;
     	wndclass.lpfnWndProc   			= WndProc ;
     	wndclass.cbClsExtra    			= 0 ;
     	wndclass.cbWndExtra    			= 0 ;
     	wndclass.hInstance     			= hInstance ;
     	wndclass.hIcon         			= LoadIcon (NULL, IDI_APPLICATION) ;
     	wndclass.hCursor       			= NULL ;
     	wndclass.hbrBackground 		= 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, TEXT ("Update Demo with Anonymous FTP"),
                       WS_OVERLAPPEDWINDOW | WS_VSCROLL,
                       CW_USEDEFAULT, CW_USEDEFAULT,
                       CW_USEDEFAULT, CW_USEDEFAULT,
                       NULL, NULL, hInstance, NULL) ;

     	ShowWindow (hwnd, iCmdShow) ;
     	UpdateWindow (hwnd) ;

          		// After window is displayed, check if the latest file exists
     	SendMessage (hwnd, WM_USER_CHECKFILES, 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 FILELIST *	plist ;
     	static int        				cxClient, cyClient, cxChar, cyChar ;
     	HDC               						hdc ;
     	int               						i ;
     	PAINTSTRUCT       				ps ;
     	SCROLLINFO        				si ;
     	SYSTEMTIME        				st ;
     	TCHAR             						szFilename [MAX_PATH] ;

     	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 (SCROLLINFO) ;
          			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_CHECKFILES:
               			// Get the system date & form filename from year and month

          			GetSystemTime (&st) ;
          			wsprintf (szFilename, TEXT ("UD%04i%02i.TXT"), st.wYear, st.wMonth) ;

               			// Check if the file exists; if so, read all the files

          			if (GetFileAttributes (szFilename) != (DWORD) -1)
          			{
               				SendMessage (hwnd, WM_USER_GETFILES, 0, 0) ;
               				return 0 ;
          			}
               			// Otherwise, get files from Internet.
               			// But first check so we don't try to copy files to a CD-ROM!

          			if (GetDriveType (NULL) == DRIVE_CDROM)
          			{
    MessageBox (hwnd, TEXT ("Cannot run this program from CD-ROM!"),
                szAppName, MB_OK | MB_ICONEXCLAMATION) ;
               				return 0 ;
          			}
               					// Ask user if an Internet connection is desired

          			if (IDYES == MessageBox (hwnd, TEXT ("Update information from Internet?"),
                        szAppName, MB_YESNO | MB_ICONQUESTION))

               					// Invoke dialog box 

      			DialogBox (hInst, szAppName, hwnd, DlgProc) ;

               					// Update display

          			SendMessage (hwnd, WM_USER_GETFILES, 0, 0) ;
          			return 0 ;

     	case 	WM_USER_GETFILES:
          			SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
          			ShowCursor (TRUE) ;

               					// Read in all the disk files

          			plist = GetFileList () ;

          			ShowCursor (FALSE) ;
          			SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               				// Simulate a WM_SIZE message to alter scroll bar & repaint

          			SendMessage (hwnd, WM_SIZE, 0, MAKELONG (cxClient, cyClient)) ;
          			InvalidateRect (hwnd, NULL, TRUE) ;
          			return 0 ;

     	case 	WM_PAINT:
          			hdc = BeginPaint (hwnd, &ps) ;
          			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 (": "), 2) ;
                    TextOutA (hdc, 0, 0, plist->info[i].szContents, 
                    strlen (plist->info[i].szContents)) ;
               				}
          			}
          			EndPaint (hwnd, &ps) ;
          			return 0 ;

     	case 	WM_DESTROY:
          			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, ¶ms) ;
          			return TRUE ;

     	case 	WM_COMMAND:
          			switch (LOWORD (wParam))
          			{
          			case 	IDCANCEL:   // button for user to abort download
               				params.bContinue = FALSE ;
               				return TRUE ;

          			case 	IDOK:      // button to make dialog box go away
               				EndDialog (hwnd, 0) ;
               				return TRUE ;
          			}
  	}
     	return FALSE ;
}

/*---------------------------------------------------------------------------
   	FtpThread: Reads files from FTP server and copies them to local disk
-----------------------------------------------------------------------------*/

void FtpThread (PVOID parg)
{
     	BOOL            						bSuccess ;
     	HINTERNET       				hIntSession, hFtpSession, hFind ;
     	HWND            						hwndStatus, hwndButton ;
     	PARAMS        				* 	pparams ;
     	TCHAR           						szBuffer [64] ;
     	WIN32_FIND_DATA 		finddata ;

     	pparams 		= parg ;
     	hwndStatus	= GetDlgItem (pparams->hwnd, IDC_STATUS) ;
     	hwndButton 	= GetDlgItem (pparams->hwnd, IDCANCEL) ;

          			// Open an internet session
     
     	hIntSession = InternetOpen (szAppName, INTERNET_OPEN_TYPE_PRECONFIG,
                                 	NULL, NULL, INTERNET_FLAG_ASYNC) ;
     	if (hIntSession == NULL)
     	{
        wsprintf (szBuffer, TEXT ("InternetOpen error %i"), GetLastError ()) ;
         		ButtonSwitch (hwndStatus, hwndButton, szBuffer) ;
          		_endthread () ;
     	}

     	SetWindowText (hwndStatus, TEXT ("Internet session opened...")) ;
          			// Check if user has pressed Cancel
     	if (!pparams->bContinue)
     	{
          		InternetCloseHandle (hIntSession) ;
          		ButtonSwitch (hwndStatus, hwndButton, NULL) ;
          		_endthread () ;
     	}

          		// Open an FTP session.
hFtpSession = InternetConnect (hIntSession, FTPSERVER, INTERNET_DEFAULT_FTP_PORT,
                              NULL, NULL, INTERNET_SERVICE_FTP, 0, 0) ;
     	if (hFtpSession == NULL)
     	{
          		InternetCloseHandle (hIntSession) ;
          		wsprintf (szBuffer, TEXT ("InternetConnect error %i"), 
                              						GetLastError ()) ;
   		ButtonSwitch (hwndStatus, hwndButton, szBuffer) ;
   		_endthread () ;
     }

	SetWindowText (hwndStatus, TEXT ("FTP Session opened...")) ;
          			// Check if user has pressed Cancel
	if (!pparams->bContinue)
     	{
          		InternetCloseHandle (hFtpSession) ;
          		InternetCloseHandle (hIntSession) ;
          		ButtonSwitch (hwndStatus, hwndButton, NULL) ;
          		_endthread () ;
     	}

          			// Set the directory
     	bSuccess = FtpSetCurrentDirectory (hFtpSession, DIRECTORY) ;
     	if (!bSuccess)
     	{
          		InternetCloseHandle (hFtpSession) ;
          		InternetCloseHandle (hIntSession) ;
          		wsprintf (	szBuffer, TEXT ("Cannot set directory to %s"),
                              						DIRECTORY) ;
          		ButtonSwitch (hwndStatus, hwndButton, szBuffer) ;
          		_endthread () ;
     	}

     	SetWindowText (hwndStatus, TEXT ("Directory found...")) ;
          		// Check if user has pressed Cancel
     	if (!pparams->bContinue)
     	{
          		InternetCloseHandle (hFtpSession) ;
          		InternetCloseHandle (hIntSession) ;
          		ButtonSwitch (hwndStatus, hwndButton, NULL) ;
          		_endthread () ;
     	}

          			// Get the first file fitting the template
     	hFind = FtpFindFirstFile (hFtpSession, TEMPLATE, &finddata, 0, 0) ;
     	if (hFind == NULL)
     	{
          		InternetCloseHandle (hFtpSession) ;
          		InternetCloseHandle (hIntSession) ;
          		ButtonSwitch (hwndStatus, hwndButton, TEXT ("Cannot find files")) ;
          		_endthread () ;
     	}

	do 
     	{
               			// Check if user has pressed Cancel
		if (!pparams->bContinue)
          		{
               			InternetCloseHandle (hFind) ;
               			InternetCloseHandle (hFtpSession) ;
               			InternetCloseHandle (hIntSession) ;
               			ButtonSwitch (hwndStatus, hwndButton, NULL) ;
               			_endthread () ;
          		}
               			// Copy file from internet to local hard disk, but fail
               			// if the file already exists locally

          		wsprintf (szBuffer, TEXT ("Reading file %s..."), finddata.cFileName) ;
          		SetWindowText (hwndStatus, szBuffer) ;

          		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:  Displays final status message and changes Cancel to 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) ;
}

/*---------------------------------------------------------------------------
   	GetFileList: Reads files from disk and saves their names and contents
-----------------------------------------------------------------------------*/

FILELIST * GetFileList (void)
{
     	DWORD           						dwRead ;
     	FILELIST      				* 	plist ;
     	HANDLE          					hFile, hFind ;
    	int             						iSize, iNum  ;
     	WIN32_FIND_DATA 		finddata ;

     	hFind = FindFirstFile (TEMPLATE, &finddata) ;
     	if (hFind == INVALID_HANDLE_VALUE)
          			return NULL ;
     	plist		= NULL ;
     	iNum 		= 0 ;

     	do
     	{
               				// Open the file and get the size
          		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 ;
       		}
               				// Realloc the FILELIST structure for a new entry 

          		plist = realloc (plist, sizeof (FILELIST) + iNum * sizeof (FILEINFO));

               				// Allocate space and save the filename 

          		plist->info[iNum].szFilename = malloc (lstrlen (finddata.cFileName) +sizeof (TCHAR)) ;
          		lstrcpy (plist->info[iNum].szFilename, finddata.cFileName) ;

               				// Allocate space and save the contents

          		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)) ;
     	FindClose (hFind) ;
          				// Sort the files by filename
     	qsort (plist->info, iNum, sizeof (FILEINFO), Compare) ;
     	plist->iNum = iNum ;
     	return plist ;
}

/*---------------------------------------------------------------------------
   	Compare function for qsort
----------------------------------------------------------------------------*/

int Compare (const FILEINFO * pinfo1, const FILEINFO * pinfo2)
{
	return lstrcmp (pinfo2->szFilename, pinfo1->szFilename) ;
}
 UPDDEMO.RC ��ժ¼��
//Microsoft Developer Studio generated resource script.
#include "resource.h"
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
// Dialog
UPDDEMO DIALOG DISCARDABLE  20, 20, 186, 95
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Internet Download"
FONT 8, "MS Sans Serif"
BEGIN
    	PUSHBUTTON  		Cancel",IDCANCEL,69,74,50,14
    	CTEXT           				"",IDC_STATUS,7,29,172,21
END
 RESOURCE.H ��ժ¼��
// Microsoft Developer Studio generated include file.
// Used by UpdDemo.rc

#define IDC_STATUS     40001

UPDDEMOʹ�õĵ���������UDyyyymm.TXT������yyyy��4λ���������ֵ���������Ȼ�����2000����mm��2λ���������ֵ�����������ٶ���ʽ��������ÿ���¶��и��µ����ĺô�����Щ���������������¿���������Ķ�Ч���ϵĿ��ǣ��ó�ʽ�������ص����ش���ý���ϡ�

��ˣ�WinMain�ں���ShowWindow��UpdateWindow����ʾUPDDEMO���Ӵ����ᣬ��WndProc���ͳ�ʽ�����WM_USER_CHECKFILESѶϢ��WndProcͨ�����Ŀǰ���ꡢ�²���������UDyyyymm.TXT�������ڵ��ڶ�Ŀ¼��������ѶϢ�����ֵ����Ĵ����������UPDDEMO�ᱻ��ȫ���£���Ȼ����ʵ������ˡ�һЩ��ʱ�ĵ�����©�������Ҫ���ø���������ʽ�ý��и��㷺�ļ�⣩������������£�UPDDEMO���Լ�����һ��WM_USER_GETFILESѶϢ����ͨ������GetFileList��ʽ������������UPDDEMO.C���Գ���һ����ʽ�������������ر����ã���������ȫ���������ǽ����е�UDyyyymm.TXT����������̬���õ�FILELIST��̬�ṹ�У��ýṹ���ڳ�ʽ��������ģ�Ȼ���ó�ʽ������ʾ������ʾ��Щ���������ݡ�

���UPDDEMOû�����µĵ�������ô������͸��Internet���и��¡���ʽ����ѯ��ʹ�����������Ƿ�OK��������ǣ���ʽ����ʾһ���򵥵ĶԻ����飬����ֻ��һ����Cancel����ť��һ��IDΪIDC_STATUS�ľ�̬������������ʱ���˾�̬��������ʹ�����ṩ״̬���棬��������ʹ����ȡ����춻����ĸ�����ҵ���˶Ի������������DlgProc��

DlgProc�̣ܶ���������һ�����������Ӵ����ŵ�PARAMS��̬�Ľṹ�Լ�һ������ΪbContinue��BOOL������Ȼ�����_ beginthread��ִ�еڶ���ִ������

FtpThread��ʽ͸��ʹ������ĺ��������ʵ�ʵĴ��䣺InternetOpen��InternetConnect��FtpSetCurrentDirectory��FtpFindFirstFile��InternetFindNextFile��FtpGetFile��InternetCloseHandle�����Σ�����ͬ�������ʽ�룬��ִ������ʽ����Թ������顢��ʹ�����˽���һ���IJ�������Լ�����ʹ��������ȡ��������ʾ����Щ���裬��ô������ü�����ࡣFtpThread��ʽ͸����hwndStatus���ź���SetWindowText����ʹ����֪����չ���������ָ���ǶԻ������м�ľ�̬��������

ִ��������������������ַ�ʽ֮һ����ֹ��

��һ�֣�FtpThread����������WinInet��ʽ���صĴ��������������������������Ŵ����ִ��ĸ�ʽ��Ȼ�Ὣ���ִ�����ͬ�Ի��������������ź͡�Cancel����ť�Ĵ���һ�𣩴��ݸ�ButtonSwitch��ButtonSwitch��һ��С��ʽ������ʾ�������ִ���������Cancel����ťת���ɡ�OK����ť����ֻ�ǰ�ť�ϵ������ִ���ת����������������ID��ת��������������ʹ���߰��¡�OK����ť�������Ի����顣

�ڶ��ַ�ʽ��FtpThread����û���κδ�����������������䴦����������������ʱ�ķ���һ����ֻ�����Ի���������ʾ���ִ�Ϊ��Internet Download Complete����

�����ַ�ʽ��ʹ���߿����ڳ�����ѡ��ȡ�����ء���ʱ��DlgProc��PARAMS�ṹ��bContinue��λ�趨ΪFALSE��FtpThreadƵ���ؼ���ֵ�����bContinue���FALSE����ô��ʽ������Ӧ�ý��е���ʰ����������NULL���ֲ�������ButtonSwitch���˲�����ʾ��ʾ���ִ���Internet Session Cancelled����ͬ����ʹ���߱��밴�¡�OK����ť���رնԻ����顣

��ȻUPDDEMOȡ�õ�ÿ������ֻ����ʾһ�У����ң���������ߣ������������ʽ��������������Ķ��ߣ�����ĸ��������Լ�������Ѷ����Ҳ��������վ�Ϸ��ָ���ϸ����Ѷ����ˣ�UPDDEMO��Ϊ������������Ѷ�ķ��������ҿ����ñ������������������һҳ֮�ᡣ