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

📄 ac_ftp.c

📁 典型的FTP 源码.不算很漂亮,但是值得学习,
💻 C
📖 第 1 页 / 共 2 页
字号:
/*---------------------------------------------------------------------
 *
 *  Program: AC_FTP.EXE Asynch Ftp Client (TCP)
 *
 *  filename: ac_ftp.c
 *
 *  copyright by Bob Quinn, 1995
 *   
 *  Description:
 *    Client application that uses "file transfer protocol" (ftp)
 *    service as described by RFC 959.  This application demonstrates
 *    bulk data transfer techniques, and reading variable length records 
 *    from a byte stream (TCP socket).  The user interface is minimized
 *    in order to emphasize the network code.
 *
 *  This software is not subject to any  export  provision  of
 *  the  United  States  Department  of  Commerce,  and may be
 *  exported to any country or planet.
 *
 *  Permission is granted to anyone to use this  software  for any  
 *  purpose  on  any computer system, and to alter it and redistribute 
 *  it freely, subject to the following  restrictions:
 *
 *  1. The author is not responsible for the consequences of
 *     use of this software, no matter how awful, even if they
 *     arise from flaws in it.
 *
 *  2. The origin of this software must not be misrepresented,
 *     either by explicit claim or by omission.  Since few users
 *     ever read sources, credits must appear in the documentation.
 *
 *  3. Altered versions must be plainly marked as such, and
 *     must not be misrepresented as being the original software.
 *     Since few users ever read sources, credits must appear in
 *     the documentation.
 *
 *  4. This notice may not be removed or altered.
 *	 
 ---------------------------------------------------------------------*/
#define STRICT
#include "..\wsa_xtra.h"
#include <windows.h>
#include <windowsx.h>

#include <string.h>    /* for _fmemcpy() & _fmemset() */
#include <winsock.h>
#include "resource.h"
#include <time.h>
#include <stdio.h>
#include <direct.h>    /* for getcwd() */
#include "..\winsockx.h"

#include "ac_ftp.h"

/* Ftp commmand strings (indexed by our command macro values) */
LPSTR aszFtpCmd[] = {
  "",    "CWD", "DELE", "PASS","PORT","RETR","STOR",
  "TYPE","USER","ABOR","LIST","PWD",  "QUIT"
};
char szAppName[] = "AC_FTP";

BOOL nAppState=NOT_CONNECTED;    /* Application State */
                                   
BOOL bToNul  =FALSE;             /* Get to NUL device file */
BOOL bFromNul=FALSE;             /* Put from NUL device file */
BOOL bIOBeep =FALSE;             /* Beep on FD_READ, FD_WRITE */
BOOL bDebug  =FALSE;             /* Debug output to WinDebug */
BOOL bReAsync=TRUE;              /* Call WSAAsyncSelect after accept() */
BOOL bLogFile=TRUE;              /* Write Cmds and Replies to logfile */

SOCKET hCtrlSock=INVALID_SOCKET; /* Ftp control socket */
SOCKET hLstnSock=INVALID_SOCKET; /* Listening data socket */
SOCKET hDataSock=INVALID_SOCKET; /* Connected data socket */

char szHost[MAXHOSTNAME]={0};    /* Remote host name or address */
char szUser[MAXUSERNAME]={0};    /* User ID */
char szPWrd[MAXPASSWORD]={0};    /* User password */

SOCKADDR_IN stCLclName;          /* Control socket name (local client) */
SOCKADDR_IN stCRmtName;          /*                     (remote server) */
SOCKADDR_IN stDLclName;          /* Data socket name (local client)*/          
SOCKADDR_IN stDRmtName;          /*                  (remote server) */
                              
char achInBuf  [INPUT_SIZE];     /* Network input data buffer */
char achOutBuf [INPUT_SIZE];     /* Network output buffer */
char szFtpRply [RPLY_SIZE]={0};  /* Ftp reply (input) buffer */
char szDataFile[MAXFILENAME]={0};/* Filename */
char szFtpCmd  [CMD_SIZE]={0};   /* Ftp command buffer */
char achRplyBuf[BUF_SIZE];       /* Reply display buffer */

/* first one (index=0) is awaiting a reply
 * second (index=1) is next to be sent, etcetera */ 
FTPCMD astFtpCmd[MAX_CMDS];      /* Ftp command queue */
int nQLen;                       /* Number of entries in Ftp cmd queue */
 
int nFtpRplyCode;                /* Ftp reply code from server */
int iNextRply;                   /* Index to next reply string */
int iLastRply;

HFILE hDataFile=HFILE_ERROR;     /* File handle for open data file */
LONG lStartTime;                 /* Start time for data transfer */
LONG lByteCount;

char szLogFile[] = "ac_ftp.log"; /* Ftp command and reply log file */
HFILE hLogFile=HFILE_ERROR;

/*--------------------------------------------------------------------
 *  Function: WinMain()
 *
 *  Description: 
 *     initialize WinSock and open main dialog box
 *
 */
int WINAPI WinMain
  (HINSTANCE hInstance,
   HINSTANCE hPrevInstance,
   LPSTR  lpszCmdLine,
   int    nCmdShow)
{
    MSG msg;
    int nRet;

    lpszCmdLine   = lpszCmdLine;   /* avoid warning */
    hPrevInstance = hPrevInstance;
    nCmdShow      = nCmdShow;
                      
    hInst = hInstance;	/* save instance handle */
                                                                
    /*-------------initialize WinSock DLL------------*/
    nRet = WSAStartup(WSA_VERSION, &stWSAData);
    /* WSAStartup() returns error value if failed (0 on success) */
    if (nRet != 0) {    
      WSAperror(nRet, "WSAStartup()", hInst);
      /* No sense continuing if we can't use WinSock */
    } else {
          
      DialogBox (hInst, MAKEINTRESOURCE(AC_FTP), NULL, Dlg_Main);
    
      /*---------------release WinSock DLL--------------*/
      nRet = WSACleanup();
      if (nRet == SOCKET_ERROR)
        WSAperror(WSAGetLastError(), "WSACleanup()", hInst);
    }    
        
    return msg.wParam;
} /* end WinMain() */

/*--------------------------------------------------------------------
 * Function: Dlg_Main()
 *
 * Description: Do all the message processing for the main dialog box
 */
BOOL CALLBACK Dlg_Main 
  (HWND hDlg,
   UINT msg,
   UINT wParam,
   LPARAM lParam)
{                      
    int nAddrSize = sizeof(SOCKADDR);
    WORD WSAEvent, WSAErr;
    SOCKET hSock;
    BOOL bOk, bRet = FALSE;
    int  nRet;
    LONG lRet;
   
    switch (msg) {
      case WSA_ASYNC+1:
        /*------------------------------------------------- 
         * Data socket async notification message handlers 
         *-------------------------------------------------*/ 
        hSock = (SOCKET)wParam;                 /* socket */
        WSAEvent = WSAGETSELECTEVENT (lParam);  /* extract event */
        WSAErr   = WSAGETSELECTERROR (lParam);  /* extract error */
        /* if error, display to user (listen socket should not have
         *  an error, but some WinSocks incorrectly post it) */
        if ((WSAErr) && (hSock == hDataSock))  {
          int i,j;
          for (i=0, j=WSAEvent; j; i++, j>>=1); /* convert bit to index */
            WSAperror(WSAErr,aszWSAEvent[i], hInst);
          /* fall-through to call reenabling function for this event */
        }
        switch (WSAEvent) {
          case FD_READ:
            if (bIOBeep)
              MessageBeep(0xFFFF);
            if (hDataSock != INVALID_SOCKET) {
              /* Receive file data or directory list */
              RecvData(hDataSock, hDataFile, achInBuf, INPUT_SIZE);
            }
            break;
          case FD_ACCEPT:
            if (hLstnSock != INVALID_SOCKET) {
              /* Accept the incoming data connection request */
              hDataSock = 
                AcceptDataConn(hLstnSock, &stDRmtName);
              nAppState |= DATACONNECTED;
              /* Close the Listening Socket */
              closesocket(hLstnSock);
              hLstnSock = INVALID_SOCKET;
              lStartTime = GetTickCount();
              /* Data transfer should begin with FD_WRITE or FD_READ.  We 
               * fall through to jumpstart sends since FD_WRITE is not 
               * always implemented correctly */
            }
          case FD_WRITE:
             /* Send file data */
            if (astFtpCmd[0].nFtpCmd == STOR) {
              lRet = SendData(&hDataSock, hDataFile, MTU_SIZE);
            }
            break;
          case FD_CLOSE:                    /* Data connection closed */
            if (hSock == hDataSock) {
              /* Read any remaining data into buffer and close connection */  
              CloseFtpConn(&hDataSock, 
                (astFtpCmd[0].nFtpCmd != STOR) ? achInBuf : (LPSTR)0, 
                INPUT_SIZE, hDlg);
              EndData ();
            }
            break;
          default:
             break;
        } /* end switch(WSAEvent) */
        break;
        
      case WSA_ASYNC: 
        /*----------------------------------------------------- 
         * Control socket async notification message handlers 
         *-----------------------------------------------------*/ 
        WSAEvent = WSAGETSELECTEVENT (lParam);  /* extract event */
        WSAErr   = WSAGETSELECTERROR (lParam);  /* extract error */
        if (WSAErr) { /* if error, display to user */
          int i,j;
          for (i=0, j=WSAEvent; j; i++, j>>=1); /* convert bit to index */
          WSAperror(WSAErr,aszWSAEvent[i], hInst);
          /* fall-through to call reenabling function for this event */
        }
        hSock = (SOCKET)wParam;                  
        switch (WSAEvent) {
          case FD_READ:
             if (!iNextRply) {
                /* Receive reply from server */
                iLastRply = RecvFtpRply(hCtrlSock, szFtpRply, RPLY_SIZE);
             }
            if (iLastRply && (iLastRply != SOCKET_ERROR)) {
                /* Display the reply Message */
                GetDlgItemText (hWinMain, IDC_REPLY, achRplyBuf, 
                  RPLY_SIZE-strlen(szFtpRply));
                wsprintf (achTempBuf, "%s%s", szFtpRply, achRplyBuf);
                SetDlgItemText (hWinMain, IDC_REPLY, achTempBuf);

		        /* Save index to next reply (if there is one) */
                nRet = strlen(szFtpRply);
                if (iLastRply > nRet+2) {
                  iNextRply = nRet+3;
                  /* Adjust if reply only had LF (no CR) */
                  if (szFtpRply[nRet+2])
                    iNextRply = nRet+2;
                }
             }

            /* Figure out what to do with reply based on last command */
            ProcessFtpRply (szFtpRply, RPLY_SIZE);
            break;
          case FD_WRITE:
            /* Send command to server */
            if (astFtpCmd[1].nFtpCmd)
              SendFtpCmd();
            break;
          case FD_CONNECT:
            /* Control connected at TCP level */
            nAppState = CTRLCONNECTED;
            wsprintf(achTempBuf, "Server: %s", szHost);
            SetDlgItemText (hDlg, IDC_SERVER, achTempBuf);
            SetDlgItemText (hDlg, IDC_STATUS, "Status: connected");
            break;
          case FD_CLOSE:
            if (nAppState & CTRLCONNECTED) {
              nAppState = NOT_CONNECTED;        /* Reset app state */
              AbortFtpCmd();
              if (hCtrlSock != INVALID_SOCKET)  /* Close control socket */
                CloseFtpConn(&hCtrlSock, (PSTR)0, 0, hDlg);
              SetDlgItemText (hDlg, IDC_SERVER, "Server: none");
              SetDlgItemText (hDlg, IDC_STATUS, "Status: not connected");
            }
            break;
          default:
             break;
        } /* end switch(WSAEvent) */
        break;

      case WM_COMMAND:
        switch (wParam) {
          case IDC_CONNECT:
             /* If we already have a socket open, tell user to close it */
             if (nAppState & CTRLCONNECTED) {
                 MessageBox (hDlg,"Close the active connection first",
                    "Can't Connect", MB_OK | MB_ICONASTERISK);
             } else {
             
               /* Prompt user for server and login user information */
               bOk = DialogBox (hInst, MAKEINTRESOURCE(IDD_SERVER),
                      hDlg, Dlg_Login);
    
               if (bOk) {
                 /* Check the destination address and resolve if necessary */
                 stCRmtName.sin_addr.s_addr = GetAddr(szHost);
                 if (stCRmtName.sin_addr.s_addr == INADDR_ANY) {
               
                   /* Tell user to enter a host */
                   wsprintf(achTempBuf, 
                     "Sorry, server %s is invalid.  Try again", szHost);
                   MessageBox (hDlg, achTempBuf,
                     "Can't connect!", MB_OK | MB_ICONASTERISK);
                 } else {
                 
                   /* Initiate connect attempt to server */
                   hCtrlSock = 
                     InitCtrlConn(&stCRmtName, hDlg, WSA_ASYNC);
                 }
               }
             }
             break;
                     
           case IDC_CLOSE:
             if (nAppState & CTRLCONNECTED) {
               /* Set application state so nothing else is processed */
               nAppState = NOT_CONNECTED;
               
               /* If we're listening, stop now */
               if (hLstnSock != INVALID_SOCKET) {
                 closesocket(hLstnSock);
                 hLstnSock = INVALID_SOCKET;
               }
               /* If there is a data connection, then abort it */
               if (hDataSock != INVALID_SOCKET)
                 QueueFtpCmd (ABOR, 0);
               /* Quit the control connection */
               if (hCtrlSock != INVALID_SOCKET)
                 QueueFtpCmd (QUIT, 0);
               SetDlgItemText (hDlg, IDC_SERVER, "Server: none");
               SetDlgItemText (hDlg, IDC_STATUS, "Status: not connected");
             }
             break;
                     
           case IDC_RETR:
             /* Prompt for name of remote file to get */
             if (nAppState & CTRLCONNECTED) {
               bOk = DialogBoxParam (hInst, MAKEINTRESOURCE(IDD_FILENAME),
                 hDlg, Dlg_File, (LONG)(LPSTR)szDataFile);
                 
               if (bOk && szDataFile[0]) {
                 if (!bToNul) {
                   /* If user provided a filename open same name here for write.
                    *  Truncate the filename to 8 chars plus 3, if necessary */
                   hDataFile = CreateLclFile (szDataFile);

⌨️ 快捷键说明

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