使用网络开发套件 2.0 的简单文件传输






4.74/5 (14投票s)
2006年12月18日
2分钟阅读

94779

4747
NDK 文件传输是一个关于如何使用 NDK 2.0 发送和接收文件的简单演示。
引言
自从我发布了文章 NDK 2.0 (网络开发套件), 我收到了很多关于如何使用 NDK 发送和接收文件的电子邮件。 对于那些不了解网络开发套件 2.0 的人来说,NDK 2.0 是一组使用 MFC 的 CSocket
类的客户端-服务器架构的简单类。 通过本文,您应该能够轻松理解使用 NDK 发送和接收文件的过程。 本文包含 2 个程序:NDK 文件传输服务器和 NDK 文件传输客户端。
算法
您不能通过简单的调用通过网络发送大文件,因为套接字将冻结。 基本思想是将文件分成许多部分并一次发送一部分。 这是这两个程序使用的过程
- 客户端向服务器发送消息,请求下载特定文件。
- 当服务器收到请求时,它会发送要上传的文件的大小。
- 当客户端收到文件的大小后,它会创建下载的文件。
- 之后,它向服务器发送消息,请求文件的下一部分。
- 当服务器收到发送下一部分的请求时,它会读取文件的下一部分并将其发送给客户端。
- 当客户端收到文件的下一部分时,它会将这一部分写入下载的文件中。
- 步骤 4-5-6 重复,直到文件到达结尾。
在这个项目中,缓冲区大小(文件的一部分)是 1024 字节。 定义 BUFFER_SIZE
在文件 NDKFileTransferCommon.h 中。
NDK 文件传输服务器
NDK 文件传输服务器向客户端提供下载文件列表。 为了最大限度地减少复杂性,NDK 文件传输服务器只接受一个客户端。 在启动服务器之前,您需要单击“添加”按钮以选择客户端将可下载的文件。
NDKFileTransferServerDlg
中的主要方法是从 CNDKServer
类重写的 OnMessage
方法
// 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 文件传输客户端
NDK 文件传输客户端可以从服务器下载文件。 为了最大限度地减少复杂性,一次只能下载一个文件。
方法 OnBnClickedButtonDownloadFiles
包含用于请求服务器启动所选文件上传的代码
// 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(); }
NDKFileTransferClientDlg
中的主要方法是从 CNDKClient
类重写的 OnMessage
方法
// 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; } }
结论
这个示例项目向您展示了服务器如何将文件发送到客户端。 但是,此项目可以扩展为支持多个客户端、同时上传到连接的客户端以及服务器和客户端之间的双向文件传输。