Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

Simple File Transfer Using the Network Development Kit 2.0

4.74/5 (14 votes)
29 Dec 20062 min read 1   4.7K  
NDK File Transfer is a simple demonstration on how to send and receive a file using the NDK 2.0.

Sample Image - NDKFileTransfer.jpg

Introduction

Since I have posted the article NDK 2.0 (Network Development Kit), I received many emails on how to send and receive a file using the NDK. For those who does not know the Network Development Kit 2.0, the NDK 2.0 is a set of simple classes for a client-server architecture using the class CSocket from MFC. With this article, you should be able to understand easily the process about sending and receiving a file with the NDK. This article contains 2 programs: an NDK File Transfer Server and an NDK File Transfer Client.

Algorithm

You can not send a big file with a simple call to over a network, because the socket will freeze. The basic idea is to split a file in many parts and send one part at a time. Here is the process used by these two programs:

  1. The client sends a message to the server asking to download the specific file.
  2. When the server receives the request, it sends the length of the file to upload.
  3. When the client receives the length of the file, it creates the downloaded file.
  4. After that, it sends a message to the server asking for the next part of the file.
  5. When the server receives the request to send the next part, it reads the next part of the file and it sends it to the client.
  6. When the client receives the next part of the file, it writes this part in the downloaded file.
  7. The steps 4-5-6 are repeated until the file will reach the end.

In this project, the buffer size (part of the file) is 1024 bytes. The define BUFFER_SIZE is in the file NDKFileTransferCommon.h.

NDK File Transfer Server

The NDK File Transfer Server provides to the client a list of files in download. To minimize the complexity, the NDK File Transfer Server accepts only one client. Before starting the server, you need to click the Add button in order to choose the files that will be available to download by the client.

The main method in the NDKFileTransferServerDlg is the overridden method OnMessage from the class CNDKServer:

// Called whenever a message is received from a user.
void CNDKFileTransferServerDlg::OnMessage(long lUserId, 
                              CNDKMessage& message)
{
    switch (message.GetId())
    {
    // The client requests a file to download
    case REQUEST_FILE:
        {
            CString strFileName;
            message.GetAt(0, strFileName);

            m_fileUpload.Open(strFileName, CFile::modeRead | 
                              CFile::shareDenyWrite);

            // Send the file length
            message.SetId(START_TRANSFERT);
            message.SetAt(0, (int)m_fileUpload.GetLength());

            SendMessageToUser(lUserId, message);

            CString strActivity;
            strActivity.Format(IDS_UPLOAD_FILE, strFileName);

            AddActivity(strActivity);
        }
        break;

    // The client asks for the next file part to download
    case REQUEST_NEXT_FILE_PART:
        {
            m_unBufferLength = m_fileUpload.Read(m_byteBuffer, BUFFER_SIZE);

            if (m_unBufferLength != 0)
            {
                // Send the file part
                message.SetId(NEXT_FILE_PART);
                message.SetAt(0, m_byteBuffer, m_unBufferLength);
            }
            else
            {
                // When there is no more read bytes,
                // send the acknowledgment that the file is completed
                message.SetId(TRANSFERT_COMPLETED);

                // Close the file if it is opened.
                if (m_fileUpload.m_hFile != INVALID_HANDLE_VALUE)
                    m_fileUpload.Close();

                CString strActivity;
                strActivity.Format(IDS_UPLOAD_FILE_COMPLETED);

                AddActivity(strActivity);
            }

            SendMessageToUser(lUserId, message);
        }
        break;
    }
}

NDK File Transfer Client

The NDK File Transfer Client can download a file from the server. To minimize the complexity, only one file at a time can be downloaded.

The method OnBnClickedButtonDownloadFiles contains the code to ask the server to start the upload of the selected file:

// Open the file
if (m_fileDownload.Open(strFileNameToCreate, 
    CFile::modeCreate | CFile::modeWrite))
{
    // Ask the server to start the download
    CNDKMessage message(REQUEST_FILE);
    message.Add(strFileName);

    SendMessageToServer(message);

    m_bIsDownloading = TRUE;

    UpdateUI();
}

The main method in the NDKFileTransferClientDlg is the overridden method OnMessage from the class CNDKClient:

// Called when a message is received.
void CNDKFileTransferClientDlg::OnMessage(CNDKMessage& message)
{
    switch (message.GetId())
    {
    case SERVER_FILES:
        {
            // Add the file name in the list
            for (int nFileIndex = 0; 
                 nFileIndex < message.GetNbElements(); nFileIndex++)
            {
                CString strFileName;

                message.GetAt(nFileIndex, strFileName);

                m_listServerFiles.AddString(strFileName);
            }

            UpdateUI();
        }
        break;

    case START_TRANSFERT:
        {
            message.GetAt(0, m_nFileSize);
            
            m_progressDownload.SetRange32(0, m_nFileSize);
            
            // Ask the server for the first file part
            message.SetId(REQUEST_NEXT_FILE_PART);
            SendMessageToServer(message);
        }
        break;

    case NEXT_FILE_PART:
        {
            message.GetAt(0, m_byteBuffer, m_unBufferLength);

            m_fileDownload.Write(m_byteBuffer, m_unBufferLength);

            m_progressDownload.OffsetPos(m_unBufferLength);

            // Ask the server for the first file part
            CNDKMessage requestMessage(REQUEST_NEXT_FILE_PART);
            SendMessageToServer(requestMessage);
        }
        break;

    case TRANSFERT_COMPLETED:
        m_fileDownload.Close();

        AfxMessageBox(IDS_FILE_DOWNLOADED_SUCCESSFULLY);

        UpdateUI();
        break;
    }
}

Conclusion

This sample project shows you how a server can send a file to a client. However, this project can be extended to support multiple clients, simultaneous uploads to connected clients, and both ways transfer of a file between the server and the client.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here