Build a Complete FTP Server

Description

This article presents a fully functional implementation of an FTP server. It can handle multiple connections at the same time (multi threaded) and has most of the features you would find in other commercial/shareware FTP servers. The server handles all basic FTP commands and offers easy user account management.

This article describes the most important classes of the application.

CFTPServer

This class is in fact the FTP server and controls all other classes needed for the server to work. Although CFTPServer is part of a dialog based application, it does not rely on an User Interface and can easily be implemented in a service or console application as well.

BOOL Start()

Activates the FTP server. It opens a listening socket (port 21) to accept connections.

void Stop()

Deactivates the server and disconnects all connected clients by terminating the running threads.

BOOL IsActive()

Is FTP server active?

void SetMaxUsers(int nValue)

Set maximum number of users

void SetPort(int nValue)

Set listening port for new connections

void SetTimeout(int nValue)

Set connection timeout (in ms). When a client does not send any commands for nValue ms, the server will close the connection.

void SetWelcomeMessage(LPCTSTR lpszText)
Set the text that will be displayed when the client logs on.

void Initialize(CFTPEventSink *pEventSink)

Set the event sink. The event sink will be the window (or any class) that receives the events generated by the FTP server. See CFTPEventSink description for more info.

CFTPEventSink

To be able to 'send' events from the CFTPServer class to the main application, I used multiple inheritance and virtual functions. The CFTPEventSink is just a helper class that contains nothing other than virtual functions. When you derive your class from CFTPEventSink, these virtual functions become a kind of events. The class CFTPServer has a reference to this class and calls the virtual funtions when it needs to notify the application.

The following 'events' are available:

void OnFTPUserConnected(DWORD nThreadID, LPCTSTR lpszUser, LPCSTR lpszAddress);

A client has successfully connected.

void OnFTPUserDisconnected(DWORD nThreadID, LPCTSTR lpszUser);

A client has disconnected.

void OnFTPStatusChange(int nType, LPCTSTR lpszText);

FTP server status has changed (file downloaded/uploaded).

void OnFTPReceivedBytesChange(int nBytes);

The number of received bytes has changed.

void OnFTPSentBytesChange(int nBytes);

The number of sent bytes received has changed.

void OnFTPStatisticChange(int nType, int nValue);

A statistic has changed; for example, the number of dowloaded or uploaded files.

Other Helper Classes

CUserManager

The class CUserManager handles all user- and file-related stuff. It checks the connected users for their access rights and converts remote to local paths. CUserManager uses Serializing to store and load the user settings.

CListenSocket

This socket is part of CFTPServer and accepts incoming connections. When a clients connects to the server, CListenSocket accepts the connection and creates a new thread (CConnectThread) that will take care of all further communication between the client and the server. After the thread has been created, CListenSocket will return to its waiting state.

CConnectThread

This thread will use CConnectSocket to handle all communication between the client and the server.

CConnectSocket

This socket class will process all incoming FTP commands and send the response back to the client.

CDataSocket

When data needs to be send or received, a CDataSocket will be created by CConnectSocket. The CDataSocket class will transfer this data (such as directory listings and files) on a seperate port.

All the other classes are just UI related and are only included to make it look a little bit fancier.

CFTPServer Usage

To use the class in your application, you need to do the following:

  1. Add the class to your application.
  2. Derive your main class from CFTPEventSink.
  3. Override the virtual functions of CFTPEventSink; these are the events that come from the server.
  4. Initialize the eventsink.
  5. Start the server.
class CMyDlg : public CDialog, CFTPEventSink
{
   ...

   CFTPServer m_FTPSERVER;

   virtual void OnFTPUserConnected(DWORD nThreadID,
                                   LPCTSTR lpszUser,
                                   LPCSTR lpszAddress);
   virtual void OnFTPUserDisconnected(DWORD nThreadID,
                                      LPCTSTR lpszUser);
   virtual void OnFTPStatusChange(int nType, LPCTSTR lpszText);
   virtual void OnFTPReceivedBytesChange(int nBytes);
   virtual void OnFTPSentBytesChange(int nBytes);
   virtual void OnFTPStatisticChange(int nType, int nValue);

   ...
}


BOOL CMyDlg::OnInitDialog()
{
   CDialog::OnInitDialog();

   ...

   // initialize event sink
   m_FTPSERVER.Initialize(this);
   // set maximum users to 10
   m_FTPSERVER.SetMaxUsers(10);
   // accept new connections on port 21
   m_FTPSERVER.SetPort(21);
   // activate server
   m_FTPSERVER.Start();

   return TRUE;
}

Contacting the Author

For any updates to this article, check my site: http://www.pablosoftwaresolutions.com.

Credits

Inspired by FileZilla Server.



Downloads

Comments

  • thanks

    Posted by dream_blue98 on 06/26/2008 10:34pm

    very god

    Reply
  • Very very good work!

    Posted by Purifier on 10/08/2007 11:28am

    Well done! keep your good work up. I really enjoyed understanding the source, implementing some of it in my own programs, and using your ftp server program from time to time. Thank you.

    Reply
  • FTPServer

    Posted by Legacy on 01/28/2004 12:00am

    Originally posted by: Roopa

    Hi,
    I downloaded your application.But,unfortunately am not able to run your application (FTPServer.exe) on my machine.
    Please, help me.
    Thanks,
    Roopa.

    • Read your Aticle

      Posted by toyocxh on 07/16/2007 09:59am

      i like it

      Reply
    Reply
  • works great! thanks

    Posted by Legacy on 11/25/2003 12:00am

    Originally posted by: me

    very much

    Reply
  • A Complete FTP Server

    Posted by Legacy on 08/06/2003 12:00am

    Originally posted by: Cary Martin

    I checked thelink and both were said to be authored by
    By Pablo van der Meer is this in error?

    Reply
  • Fatal Compiler Error in C++ 7.0

    Posted by Legacy on 01/21/2003 12:00am

    Originally posted by: Paul

    Does anyone know a fix for this?

    Compiler error in ConnectThread.cpp with MS C++ 7.


    BEGIN_MESSAGE_MAP(CConnectThread, CWinThread)
    //{{AFX_MSG_MAP(CConnectThread)
    //}}AFX_MSG_MAP
    ON_MESSAGE(WM_THREADMSG, OnThreadMessage)
    END_MESSAGE_MAP()

    Compiler error is:

    error C2440: 'static_cast' : cannot convert from 'LRESULT (__thiscall CConnectThread::* )(WPARAM,LPARAM)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'

    Reply
  • [Q&A] Problem on static library.

    Posted by Legacy on 12/11/2002 12:00am

    Originally posted by: JeongDong, Lee

    Q> To avoid problem on shared library I'm used to set "Static Library Link".

    Changing settings in this project lead to fatal errors during execution (just recompile and open a ftp connection).

    Can the author or anyone else spot this problem ?
    TIA
    Davide

    A>
    Re: Problem on static library PablovanderMeer 5:02 8 Sep '02
    This problem is discussed in MSDN: Q193101
    Thanxs, You're right, just insert in ConnectThread.cpp
    ...
    BOOL CConnectThread::InitInstance()
    {
    #ifndef _AFXDLL
    VERIFY( AfxSocketInit()); // This solve statical link problem
    #endif
    try
    {
    ....

    and it works in both configuration.

    Davide

    //**********************************************************
    //*BOOL CConnectThread::InitInstance()
    //*
    //*#ifndef _AFXDLL
    //*VERIFY( AfxSocketInit()); // This solve statical link *problem
    //*#endif
    //**********************************************************

    Reply
  • Setup only one data connection for each client

    Posted by Legacy on 10/07/2002 12:00am

    Originally posted by: Ruca

    How can I setup only one data connection for each user? What changes I have to do in source code?
    For example:
    1- a client connect;
    2- he downloads a file from the sever;
    3- he upload another file to the server;
    4- he list the files from a folder;

    I want that the client uses the same data connection for the steps 2, 3 and 4. How can I do that???

    Thanks,
    Ruca

    Reply
  • Good GUI

    Posted by Legacy on 08/13/2002 12:00am

    Originally posted by: Andrew Fenster

    I don't really need an FTP server at the moment, but I really liked your application's GUI. It's much fancier that what I usually do. I've looked through the code and I learned a lot of new tricks. I'm STILL looking at it.

    I'm overhauling an application at work at the moment, and I'm thinking the new app may end up looking more like yours.

    Thanks a lot. Keep up the good work.

    Reply
  • Code is ripped off from GPL program, but no credits given to the authors. vai vai vai

    Posted by Legacy on 08/02/2002 12:00am

    Originally posted by: Andrey Koubychev

    Take a look
    http://www.codeproject.com/internet/FTPServer.asp?df=100&forumid=4270&select=232565#xx232565xx

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Hybrid cloud platforms need to think in terms of sweet spots when it comes to application platform interface (API) integration. Cloud Velocity has taken a unique approach to tight integration with the API sweet spot; enough to support the agility of physical and virtual apps, including multi-tier environments and databases, while reducing capital and operating costs. Read this case study to learn how a global-level Fortune 1000 company was able to deploy an entire 6+ TB Oracle eCommerce stack in Amazon Web …

  • Protecting business operations means shifting the priorities around availability from disaster recovery to business continuity. Enterprises are shifting their focus from recovery from a disaster to preventing the disaster in the first place. With this change in mindset, disaster recovery is no longer the first line of defense; the organizations with a smarter business continuity practice are less impacted when disasters strike. This SmartSelect will provide insight to help guide your enterprise toward better …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds