VC++ 实现文件上传下载服务器端
2017-02-15 17:04
387 查看
#pragma once
#include <afxsock.h>
#define WM_FILELIST WM_USER + 101 //接收文件列表
#define WM_FILEUPDATE WM_USER + 102 //反映文件下载状态
#define WM_FILEDOWNLOAD WM_USER + 103 //发送文件列表
#define FILELIST 1000 //请求文件列表
#define FILEUPDATE 2000 //请求文件上传
#define FILEDOWNLOAD 3000 //请求文件下载
#define RECVSIZE 1024*16 //一次性发送/接收的数据块大小
//与服务器通信语言结构
typedef struct
{
int iCommand;
long lFileOffset;
long lFileLength;
char sFilePath[128];
}MSGFILE;
//请求线程参数
typedef struct
{
char sIP[15]; //IP地址
int iPort; //端口
MSGFILE msgFile; //通信语言结构
LPVOID ptr; //指针
}MSGPARAM;
//文件列表结构
typedef struct
{
long lFileLength;
char sFilePath[128];
}MSGFILELIST;
//反映文件状态的结构
typedef struct
{
long lFileOffset;//偏移
char sFilePath[128];//路径
}MSGFILESTATUS;
//接收线程参数
typedef struct
{
SOCKET sock;
LPVOID ptr;
}PARAMRECV;
//服务器端 类 头文件
// Ftp_Server.h: interface for the CFtp_Server class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FTP_SERVER_H__DCFE7BE8_C212_475E_AAC8_811898047B46__INCLUDED_)
#define AFX_FTP_SERVER_H__DCFE7BE8_C212_475E_AAC8_811898047B46__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "basedef.h"
#define WM_FINISHUPDATE WM_USER+401
class CFtp_Server
{
public:
CFtp_Server();
virtual ~CFtp_Server();
BOOL StartListen(CWnd *pWnd, int nPort, char *sPath);
void StopListen();
protected:
//监听线程
static DWORD WINAPI ListenThread(LPVOID lpParam);
//接收线程
static DWORD WINAPI RecvThread(LPVOID lpParam);
private:
//监听线程结束符
BOOL m_bEndListenThread;
//监听端口
int m_iListenPort;
//窗口指针
CWnd* m_pWnd;
//服务器套接字
SOCKET m_socket;
//保存本机地址
SOCKADDR_IN m_sin;
//存储路径
char m_sPath[128];
};
#endif // !defined(AFX_FTP_SERVER_H__DCFE7BE8_C212_475E_AAC8_811898047B46__INCLUDED_)
//服务器端 类 CPP
// Ftp_Server.cpp: implementation of the CFtp_Server class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Ftp_Server.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CFtp_Server::CFtp_Server()
{
}
CFtp_Server::~CFtp_Server()
{
}
BOOL CFtp_Server::StartListen(CWnd *pWnd, int nPort, char *sPath)
{
//初始化套接字
if (!AfxSocketInit())
{
return FALSE;
}
//获得端口号和窗口指针
m_iListenPort = nPort;
m_pWnd = pWnd;
strcpy(m_sPath, sPath);
m_bEndListenThread = FALSE;//开始监听
DWORD id;
HANDLE h = CreateThread(NULL, 0, ListenThread, this, 0, &id);//创建句柄
//线程要执行的函数为ThreadListen,将this指针传递给线程,线程ID为id,创建成功,返回新线程的一个句柄
CloseHandle(h); //关闭句柄,并不终止线程
return TRUE;
}
void CFtp_Server::StopListen()
{
m_bEndListenThread = TRUE;
Sleep(100);
closesocket(m_socket);
}
DWORD WINAPI CFtp_Server::ListenThread(LPVOID lpParam)
{
CFtp_Server* pServer = (CFtp_Server*)lpParam;
SOCKET sockListen = socket(AF_INET, SOCK_STREAM, 0);//创建socket
//地址家族为internet,用于TCP和UDP,字节流,特定的协议
SOCKADDR_IN sin; //转换地址
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0; //ip地址,以网路字节顺序。
sin.sin_port = htons(pServer->m_iListenPort);
if (bind(sockListen, (SOCKADDR*)&sin, sizeof(sin)) == SOCKET_ERROR)
{
closesocket(sockListen); //关闭socket
return FALSE;
}
if (listen(sockListen, 5) == SOCKET_ERROR)
{//若将socket置于监听失败
closesocket(sockListen);
return FALSE;
}
fd_set fdListen;//结构体,将socket放进一个集合
timeval seltime;//结构体,指定时间值(秒+毫秒)
seltime.tv_sec = 0; //秒
seltime.tv_usec = 10000;//毫秒==10秒
while (!pServer->m_bEndListenThread)
{//服务器在监听状态
FD_ZERO(&fdListen);//将集合清零
FD_SET(sockListen, &fdListen);//将socket添加到set中
if (select(0, &fdListen, NULL, NULL, &seltime) <= 0 || !FD_ISSET(sockListen, &fdListen))
continue;
//如果在规定时间内,set中无socket可读出||socket不在set中,结束本次循环,继续下次循环
int len = sizeof(sin);
SOCKET sock = accept(sockListen, (SOCKADDR*)&sin, &len);
//接受socket上的连接
PARAMRECV* pParamRecv = new PARAMRECV;//结构体,接收线程参数
pParamRecv->sock = sock;
pParamRecv->ptr = pServer;
DWORD id;
HANDLE h = CreateThread(NULL, 0, RecvThread, pParamRecv, 0, &id);
//创建ThreadRecv线程,将pParamRecv传递给线程
CloseHandle(h);
}
return 0;
}
DWORD WINAPI CFtp_Server::RecvThread(LPVOID lpParam)
{
PARAMRECV* pParam = (PARAMRECV*)lpParam;//指向接收线程的指针
CFtp_Server* pServer = (CFtp_Server*)pParam->ptr;//指向Server的指针
fd_set fdRecv;//结构体,接收线程集合
timeval seltime;//结构体,指定时间值==10s
seltime.tv_sec = 0;
seltime.tv_usec = 10000;
while (1)
{
FD_ZERO(&fdRecv);//集合清零
FD_SET(pParam->sock, &fdRecv);//将已连接的socket加入集合
if (select(0, &fdRecv, NULL, NULL, &seltime) <= 0 || !FD_ISSET(pParam->sock, &fdRecv))
continue;
//如果在指定时间内,结构体内无可读接收线程||sock不在结构体内
MSGFILE msgFile;
int iRecvCnt = recv(pParam->sock, (char*)&msgFile, sizeof(msgFile), 0);
//成功,返回接收字节数;正常结束,返回0;否则<0
if (iRecvCnt <= 0)
break;
//请求文件列表
if (msgFile.iCommand == FILELIST)
{
while (!pServer->m_bEndListenThread)
{
MSGFILELIST msgFileList;
iRecvCnt = recv(pParam->sock, (char*)&msgFileList, sizeof(msgFileList), 0);
if (iRecvCnt <= 0)
4000
break;
pServer->m_pWnd->SendMessage(WM_FILELIST, (WPARAM)&msgFileList, 0);
}
}
//请求文件下载
else if (msgFile.iCommand == FILEDOWNLOAD)
{
long lFileOffset = msgFile.lFileOffset;//文件偏移
CFile file;
CString strPath, strName;
strPath.Format("%s", msgFile.sFilePath);
int iPos = strPath.ReverseFind('\\');
strName = strPath.Right(strPath.GetLength() - iPos - 1);
strPath.Format("%s", pServer->m_sPath);
strPath += strName;
BOOL bResult = file.Open(strPath, CFile::modeRead | CFile::shareDenyNone, NULL);
//打开指定路径的文件,只读||可共享,成功,返回非零;否则,0
if (!bResult)
{
break;
}
char sSendBuf[RECVSIZE];//发送缓冲区,16K
while (lFileOffset < msgFile.lFileLength)
{
int iSeek = file.Seek(lFileOffset, CFile::begin);//寻找新的文件偏移,距离开始处
int iReadCnt = file.Read(sSendBuf, RECVSIZE);
if (iReadCnt == 0)
break;
int iSendCnt = send(pParam->sock, sSendBuf, iReadCnt, 0);
//如果发送失败就终止线程
if (iSendCnt == -1)
break;
else
lFileOffset += iSendCnt;//修改偏移量
}
file.Close();
}
//请求文件上传
else if (msgFile.iCommand == FILEUPDATE)
{
char sRecvBuf[RECVSIZE] = "\0"; //接收缓冲区置空
long lFileOffset = msgFile.lFileOffset;
CFile file;
//将客户端路径改为服务端保存路径
CString strPath, strName;
strPath.Format("%s", msgFile.sFilePath);
int iPos = strPath.ReverseFind('\\');
strName = strPath.Right(strPath.GetLength() - iPos - 1);
strPath.Format("%s", pServer->m_sPath);
strPath += strName;
BOOL bResult = file.Open(strPath, CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate, NULL);
//打开接收端文件,写模式||若创建的文件已存在,不截短。
while (bResult && lFileOffset < msgFile.lFileLength)
{
int iRecvCnt = recv(pParam->sock, sRecvBuf, RECVSIZE, 0);
if (iRecvCnt <= 0)
break;
file.Seek(lFileOffset, CFile::begin);
file.Write(sRecvBuf, iRecvCnt);
lFileOffset += iRecvCnt;//修改偏移
MSGFILESTATUS msgFileStatus;//文件状态结构体
msgFileStatus.lFileOffset = lFileOffset;
strcpy(msgFileStatus.sFilePath, msgFile.sFilePath);
pServer->m_pWnd->SendMessage(WM_FILEUPDATE, (WPARAM)&msgFileStatus, 0);
}
file.Close();
pServer->m_pWnd->SendMessage(WM_FINISHUPDATE, 0, 0);
}
break;
}
delete pParam;
return 0;
}
//对话框 头文件
// Server_FTPDlg.h : header file
//
#if !defined(AFX_SERVER_FTPDLG_H__492B251E_B713_4E0F_A5A4_C1BC9EB8EF08__INCLUDED_)
#define AFX_SERVER_FTPDLG_H__492B251E_B713_4E0F_A5A4_C1BC9EB8EF08__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Ftp_Server.h"
/////////////////////////////////////////////////////////////////////////////
// CServer_FTPDlg dialog
class CServer_FTPDlg : public CDialog
{
// Construction
public:
void InitListColumn();
CServer_FTPDlg(CWnd* pParent = NULL); // standard constructor
CFtp_Server *m_pFtp_Server;
BOOL m_bConnected; //已连接
int m_nUpdateNum; //已上传文件
// Dialog Data
//{{AFX_DATA(CServer_FTPDlg)
enum { IDD = IDD_SERVER_FTP_DIALOG };
CListCtrl m_ListFile;
int m_nPort;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CServer_FTPDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CServer_FTPDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnBtnListen();
afx_msg void OnBtnScan();
afx_msg void OnDestroy();
//}}AFX_MSG
afx_msg LRESULT OnFileList(WPARAM wp, LPARAM lp);
afx_msg LRESULT OnFileUpdate(WPARAM wp, LPARAM lp);
afx_msg LRESULT OnFinishUpdate(WPARAM wp, LPARAM lp);
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_SERVER_FTPDLG_H__492B251E_B713_4E0F_A5A4_C1BC9EB8EF08__INCLUDED_)
//对话框 CPP文件
// Server_FTPDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Server_FTP.h"
#include "Server_FTPDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServer_FTPDlg dialog
CServer_FTPDlg::CServer_FTPDlg(CWnd* pParent /*=NULL*/)
: CDialog(CServer_FTPDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CServer_FTPDlg)
m_nPort = 7000;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_bConnected = FALSE;
m_nUpdateNum = 0;
}
void CServer_FTPDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CServer_FTPDlg)
DDX_Control(pDX, IDC_LIST_FILE, m_ListFile);
DDX_Text(pDX, IDC_EDIT_PORT, m_nPort);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CServer_FTPDlg, CDialog)
//{{AFX_MSG_MAP(CServer_FTPDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_ERASEBKGND()
ON_BN_CLICKED(IDC_BTN_LISTEN, OnBtnListen)
ON_BN_CLICKED(IDC_BTN_SCAN, OnBtnScan)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_FILELIST, OnFileList)
ON_MESSAGE(WM_FILEUPDATE, OnFileUpdate)
ON_MESSAGE(WM_FINISHUPDATE, OnFinishUpdate)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServer_FTPDlg message handlers
BOOL CServer_FTPDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
InitListColumn();
m_pFtp_Server = new CFtp_Server();
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CServer_FTPDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CServer_FTPDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CServer_FTPDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
BOOL CServer_FTPDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
//更改背景颜色
CRect rect;
GetClientRect(&rect);
pDC->FillSolidRect(&rect, RGB(202, 225, 243));
return TRUE;
// return CDialog::OnEraseBkgnd(pDC);
}
void CServer_FTPDlg::OnBtnListen()
{
// TODO: Add your control notification handler code here
if (m_bConnected)
{
m_pFtp_Server->StopListen();
SetDlgItemText(IDC_BTN_LISTEN, _T("启动监听"));
GetDlgItem(IDC_EDIT_PORT)->EnableWindow(TRUE);
m_bConnected = FALSE;
return;
}
CString sPath;
GetDlgItemText(IDC_EDIT_PATH, sPath);
if (sPath.IsEmpty())
{
AfxMessageBox(_T("请先设置文件存储路径!"));
return;
}
int nPort = GetDlgItemInt(IDC_EDIT_PORT);
if (m_pFtp_Server->StartListen(this, nPort, sPath.GetBuffer(0)))
{
SetDlgItemText(IDC_BTN_LISTEN, _T("停止监听"));
GetDlgItem(IDC_EDIT_PORT)->EnableWindow(FALSE);
m_bConnected = TRUE;
return;
}
AfxMessageBox(_T("服务器启动失败!"));
}
void CServer_FTPDlg::OnBtnScan()
{
// TODO: Add your control notification handler code here
BROWSEINFO bi; //定义后面将被SHBrowseForFolder调用参数
char buffer[MAX_PATH];
ZeroMemory(buffer,MAX_PATH);
bi.hwndOwner = this->m_hWnd;
bi.pidlRoot = NULL;
bi.pszDisplayName=buffer;
bi.lpszTitle = "指定文件夹";
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.lParam = 0;
bi.iImage = 0;
LPITEMIDLIST pList = NULL;
if((pList=SHBrowseForFolder(&bi)) != NULL)
{
char path[MAX_PATH];
ZeroMemory(path,MAX_PATH);
SHGetPathFromIDList(pList,path);//根据你设置的属性 打开 返回路径到path
SetDlgItemText(IDC_EDIT_PATH, path);
}
}
void CServer_FTPDlg::InitListColumn()
{
int iWidth = 50;
m_ListFile.InsertColumn(0, "文件名", LVCFMT_LEFT, 3*iWidth, -1);
m_ListFile.InsertColumn(1, "文件大小", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(2, "上传速度", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(3, "上传状态", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(4, "上传时间", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(5, "文件保存路径", LVCFMT_LEFT, 5*iWidth, -1);
m_ListFile.InsertColumn(6, "时间标记", LVCFMT_LEFT, 2*iWidth, -1);
//插入列:左对齐,无子列
m_ListFile.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
}
void CServer_FTPDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
if(m_pFtp_Server != NULL)
{
m_pFtp_Server->StopListen();
delete m_pFtp_Server;
}
}
LRESULT CServer_FTPDlg::OnFileUpdate(WPARAM wp, LPARAM lp)
{
MSGFILESTATUS* pmsg = (MSGFILESTATUS*)wp;
CString strPath;
strPath.Format("%s", pmsg->sFilePath);
int iTotal = m_ListFile.GetItemCount();
int iSel = 0;
for(; iSel<iTotal; iSel++)
{
CString strListPath;
strListPath = m_ListFile.GetItemText(iSel, 5);
if(strPath.Compare(strListPath) == 0)//路径相同
break;
}
if(iSel == iTotal)
return 1;
long lFileLength = m_ListFile.GetItemData(iSel);
CString strStatus;
strStatus.Format("%0.2f%%", (float)pmsg->lFileOffset/lFileLength*100);
//显示状态 %,精确到小数点后两位
m_ListFile.SetItemText(iTotal-1, 3, strStatus.GetBuffer(0));
//显示时间
DWORD dwNowTick, dwStartTick;//毫秒
dwNowTick = GetTickCount();
sscanf(m_ListFile.GetItemText(iSel, 6), "%u", &dwStartTick);
long iEllapsed = (dwNowTick-dwStartTick);//间隔:微秒
strStatus.Format("%dms", iEllapsed);
m_ListFile.SetItemText(iSel, 4, strStatus.GetBuffer(0));
//显示速度
if(iEllapsed > 0)
{
strStatus.Format("%dk/s", (pmsg->lFileOffset/1024/iEllapsed)*1000);
m_ListFile.SetItemText(iSel, 2, strStatus.GetBuffer(0));
}
return 0;
}
LRESULT CServer_FTPDlg::OnFileList(WPARAM wp, LPARAM lp)
{
MSGFILELIST* pmsgList = (MSGFILELIST*)wp;
int iItem = m_ListFile.GetItemCount();
for (int i = m_nUpdateNum; i < iItem; i++)
{
m_ListFile.DeleteItem(i);
}
iItem = m_nUpdateNum;
CString strServerPath, strFileName, strFileSize;
strServerPath.Format("%s", pmsgList->sFilePath);
int iPos = strServerPath.ReverseFind('\\');
//设置文件名到缓冲区
strFileName = strServerPath.Right(strServerPath.GetLength()-iPos-1);
strFileSize.Format("%0.2fk", (float)pmsgList->lFileLength/1024);
LV_ITEM lvi;
lvi.mask = LVIF_TEXT|LVIF_PARAM;
lvi.iItem = iItem;
lvi.iSubItem = 0;
lvi.lParam = pmsgList->lFileLength;
//显示
lvi.pszText
96b1
= strFileName.GetBuffer(0);
m_ListFile.InsertItem(&lvi);
m_ListFile.SetItemText(iItem, 1, strFileSize.GetBuffer(0));
m_ListFile.SetItemText(iItem, 5, strServerPath.GetBuffer(0));
//设置初始时间点
DWORD dwStartTick = GetTickCount();
char sStartTick[20];
sprintf(sStartTick, "%u", dwStartTick);
m_ListFile.SetItemText(iItem, 6, sStartTick);
return 0;
}
LRESULT CServer_FTPDlg::OnFinishUpdate(WPARAM wp, LPARAM lp)
{
++ m_nUpdateNum;
return 0;
}
#pragma once
#include <afxsock.h>
#define WM_FILELIST WM_USER + 101 //接收文件列表
#define WM_FILEUPDATE WM_USER + 102 //反映文件下载状态
#define WM_FILEDOWNLOAD WM_USER + 103 //发送文件列表
#define FILELIST 1000 //请求文件列表
#define FILEUPDATE 2000 //请求文件上传
#define FILEDOWNLOAD 3000 //请求文件下载
#define RECVSIZE 1024*16 //一次性发送/接收的数据块大小
//与服务器通信语言结构
typedef struct
{
int iCommand;
long lFileOffset;
long lFileLength;
char sFilePath[128];
}MSGFILE;
//请求线程参数
typedef struct
{
char sIP[15]; //IP地址
int iPort; //端口
MSGFILE msgFile; //通信语言结构
LPVOID ptr; //指针
}MSGPARAM;
//文件列表结构
typedef struct
{
long lFileLength;
char sFilePath[128];
}MSGFILELIST;
//反映文件状态的结构
typedef struct
{
long lFileOffset;//偏移
char sFilePath[128];//路径
}MSGFILESTATUS;
//接收线程参数
typedef struct
{
SOCKET sock;
LPVOID ptr;
}PARAMRECV;
//服务器端 类 头文件
// Ftp_Server.h: interface for the CFtp_Server class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FTP_SERVER_H__DCFE7BE8_C212_475E_AAC8_811898047B46__INCLUDED_)
#define AFX_FTP_SERVER_H__DCFE7BE8_C212_475E_AAC8_811898047B46__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "basedef.h"
#define WM_FINISHUPDATE WM_USER+401
class CFtp_Server
{
public:
CFtp_Server();
virtual ~CFtp_Server();
BOOL StartListen(CWnd *pWnd, int nPort, char *sPath);
void StopListen();
protected:
//监听线程
static DWORD WINAPI ListenThread(LPVOID lpParam);
//接收线程
static DWORD WINAPI RecvThread(LPVOID lpParam);
private:
//监听线程结束符
BOOL m_bEndListenThread;
//监听端口
int m_iListenPort;
//窗口指针
CWnd* m_pWnd;
//服务器套接字
SOCKET m_socket;
//保存本机地址
SOCKADDR_IN m_sin;
//存储路径
char m_sPath[128];
};
#endif // !defined(AFX_FTP_SERVER_H__DCFE7BE8_C212_475E_AAC8_811898047B46__INCLUDED_)
//服务器端 类 CPP
// Ftp_Server.cpp: implementation of the CFtp_Server class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Ftp_Server.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CFtp_Server::CFtp_Server()
{
}
CFtp_Server::~CFtp_Server()
{
}
BOOL CFtp_Server::StartListen(CWnd *pWnd, int nPort, char *sPath)
{
//初始化套接字
if (!AfxSocketInit())
{
return FALSE;
}
//获得端口号和窗口指针
m_iListenPort = nPort;
m_pWnd = pWnd;
strcpy(m_sPath, sPath);
m_bEndListenThread = FALSE;//开始监听
DWORD id;
HANDLE h = CreateThread(NULL, 0, ListenThread, this, 0, &id);//创建句柄
//线程要执行的函数为ThreadListen,将this指针传递给线程,线程ID为id,创建成功,返回新线程的一个句柄
CloseHandle(h); //关闭句柄,并不终止线程
return TRUE;
}
void CFtp_Server::StopListen()
{
m_bEndListenThread = TRUE;
Sleep(100);
closesocket(m_socket);
}
DWORD WINAPI CFtp_Server::ListenThread(LPVOID lpParam)
{
CFtp_Server* pServer = (CFtp_Server*)lpParam;
SOCKET sockListen = socket(AF_INET, SOCK_STREAM, 0);//创建socket
//地址家族为internet,用于TCP和UDP,字节流,特定的协议
SOCKADDR_IN sin; //转换地址
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0; //ip地址,以网路字节顺序。
sin.sin_port = htons(pServer->m_iListenPort);
if (bind(sockListen, (SOCKADDR*)&sin, sizeof(sin)) == SOCKET_ERROR)
{
closesocket(sockListen); //关闭socket
return FALSE;
}
if (listen(sockListen, 5) == SOCKET_ERROR)
{//若将socket置于监听失败
closesocket(sockListen);
return FALSE;
}
fd_set fdListen;//结构体,将socket放进一个集合
timeval seltime;//结构体,指定时间值(秒+毫秒)
seltime.tv_sec = 0; //秒
seltime.tv_usec = 10000;//毫秒==10秒
while (!pServer->m_bEndListenThread)
{//服务器在监听状态
FD_ZERO(&fdListen);//将集合清零
FD_SET(sockListen, &fdListen);//将socket添加到set中
if (select(0, &fdListen, NULL, NULL, &seltime) <= 0 || !FD_ISSET(sockListen, &fdListen))
continue;
//如果在规定时间内,set中无socket可读出||socket不在set中,结束本次循环,继续下次循环
int len = sizeof(sin);
SOCKET sock = accept(sockListen, (SOCKADDR*)&sin, &len);
//接受socket上的连接
PARAMRECV* pParamRecv = new PARAMRECV;//结构体,接收线程参数
pParamRecv->sock = sock;
pParamRecv->ptr = pServer;
DWORD id;
HANDLE h = CreateThread(NULL, 0, RecvThread, pParamRecv, 0, &id);
//创建ThreadRecv线程,将pParamRecv传递给线程
CloseHandle(h);
}
return 0;
}
DWORD WINAPI CFtp_Server::RecvThread(LPVOID lpParam)
{
PARAMRECV* pParam = (PARAMRECV*)lpParam;//指向接收线程的指针
CFtp_Server* pServer = (CFtp_Server*)pParam->ptr;//指向Server的指针
fd_set fdRecv;//结构体,接收线程集合
timeval seltime;//结构体,指定时间值==10s
seltime.tv_sec = 0;
seltime.tv_usec = 10000;
while (1)
{
FD_ZERO(&fdRecv);//集合清零
FD_SET(pParam->sock, &fdRecv);//将已连接的socket加入集合
if (select(0, &fdRecv, NULL, NULL, &seltime) <= 0 || !FD_ISSET(pParam->sock, &fdRecv))
continue;
//如果在指定时间内,结构体内无可读接收线程||sock不在结构体内
MSGFILE msgFile;
int iRecvCnt = recv(pParam->sock, (char*)&msgFile, sizeof(msgFile), 0);
//成功,返回接收字节数;正常结束,返回0;否则<0
if (iRecvCnt <= 0)
break;
//请求文件列表
if (msgFile.iCommand == FILELIST)
{
while (!pServer->m_bEndListenThread)
{
MSGFILELIST msgFileList;
iRecvCnt = recv(pParam->sock, (char*)&msgFileList, sizeof(msgFileList), 0);
if (iRecvCnt <= 0)
4000
break;
pServer->m_pWnd->SendMessage(WM_FILELIST, (WPARAM)&msgFileList, 0);
}
}
//请求文件下载
else if (msgFile.iCommand == FILEDOWNLOAD)
{
long lFileOffset = msgFile.lFileOffset;//文件偏移
CFile file;
CString strPath, strName;
strPath.Format("%s", msgFile.sFilePath);
int iPos = strPath.ReverseFind('\\');
strName = strPath.Right(strPath.GetLength() - iPos - 1);
strPath.Format("%s", pServer->m_sPath);
strPath += strName;
BOOL bResult = file.Open(strPath, CFile::modeRead | CFile::shareDenyNone, NULL);
//打开指定路径的文件,只读||可共享,成功,返回非零;否则,0
if (!bResult)
{
break;
}
char sSendBuf[RECVSIZE];//发送缓冲区,16K
while (lFileOffset < msgFile.lFileLength)
{
int iSeek = file.Seek(lFileOffset, CFile::begin);//寻找新的文件偏移,距离开始处
int iReadCnt = file.Read(sSendBuf, RECVSIZE);
if (iReadCnt == 0)
break;
int iSendCnt = send(pParam->sock, sSendBuf, iReadCnt, 0);
//如果发送失败就终止线程
if (iSendCnt == -1)
break;
else
lFileOffset += iSendCnt;//修改偏移量
}
file.Close();
}
//请求文件上传
else if (msgFile.iCommand == FILEUPDATE)
{
char sRecvBuf[RECVSIZE] = "\0"; //接收缓冲区置空
long lFileOffset = msgFile.lFileOffset;
CFile file;
//将客户端路径改为服务端保存路径
CString strPath, strName;
strPath.Format("%s", msgFile.sFilePath);
int iPos = strPath.ReverseFind('\\');
strName = strPath.Right(strPath.GetLength() - iPos - 1);
strPath.Format("%s", pServer->m_sPath);
strPath += strName;
BOOL bResult = file.Open(strPath, CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate, NULL);
//打开接收端文件,写模式||若创建的文件已存在,不截短。
while (bResult && lFileOffset < msgFile.lFileLength)
{
int iRecvCnt = recv(pParam->sock, sRecvBuf, RECVSIZE, 0);
if (iRecvCnt <= 0)
break;
file.Seek(lFileOffset, CFile::begin);
file.Write(sRecvBuf, iRecvCnt);
lFileOffset += iRecvCnt;//修改偏移
MSGFILESTATUS msgFileStatus;//文件状态结构体
msgFileStatus.lFileOffset = lFileOffset;
strcpy(msgFileStatus.sFilePath, msgFile.sFilePath);
pServer->m_pWnd->SendMessage(WM_FILEUPDATE, (WPARAM)&msgFileStatus, 0);
}
file.Close();
pServer->m_pWnd->SendMessage(WM_FINISHUPDATE, 0, 0);
}
break;
}
delete pParam;
return 0;
}
//对话框 头文件
// Server_FTPDlg.h : header file
//
#if !defined(AFX_SERVER_FTPDLG_H__492B251E_B713_4E0F_A5A4_C1BC9EB8EF08__INCLUDED_)
#define AFX_SERVER_FTPDLG_H__492B251E_B713_4E0F_A5A4_C1BC9EB8EF08__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Ftp_Server.h"
/////////////////////////////////////////////////////////////////////////////
// CServer_FTPDlg dialog
class CServer_FTPDlg : public CDialog
{
// Construction
public:
void InitListColumn();
CServer_FTPDlg(CWnd* pParent = NULL); // standard constructor
CFtp_Server *m_pFtp_Server;
BOOL m_bConnected; //已连接
int m_nUpdateNum; //已上传文件
// Dialog Data
//{{AFX_DATA(CServer_FTPDlg)
enum { IDD = IDD_SERVER_FTP_DIALOG };
CListCtrl m_ListFile;
int m_nPort;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CServer_FTPDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CServer_FTPDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnBtnListen();
afx_msg void OnBtnScan();
afx_msg void OnDestroy();
//}}AFX_MSG
afx_msg LRESULT OnFileList(WPARAM wp, LPARAM lp);
afx_msg LRESULT OnFileUpdate(WPARAM wp, LPARAM lp);
afx_msg LRESULT OnFinishUpdate(WPARAM wp, LPARAM lp);
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_SERVER_FTPDLG_H__492B251E_B713_4E0F_A5A4_C1BC9EB8EF08__INCLUDED_)
//对话框 CPP文件
// Server_FTPDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Server_FTP.h"
#include "Server_FTPDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServer_FTPDlg dialog
CServer_FTPDlg::CServer_FTPDlg(CWnd* pParent /*=NULL*/)
: CDialog(CServer_FTPDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CServer_FTPDlg)
m_nPort = 7000;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_bConnected = FALSE;
m_nUpdateNum = 0;
}
void CServer_FTPDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CServer_FTPDlg)
DDX_Control(pDX, IDC_LIST_FILE, m_ListFile);
DDX_Text(pDX, IDC_EDIT_PORT, m_nPort);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CServer_FTPDlg, CDialog)
//{{AFX_MSG_MAP(CServer_FTPDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_ERASEBKGND()
ON_BN_CLICKED(IDC_BTN_LISTEN, OnBtnListen)
ON_BN_CLICKED(IDC_BTN_SCAN, OnBtnScan)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_FILELIST, OnFileList)
ON_MESSAGE(WM_FILEUPDATE, OnFileUpdate)
ON_MESSAGE(WM_FINISHUPDATE, OnFinishUpdate)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServer_FTPDlg message handlers
BOOL CServer_FTPDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
InitListColumn();
m_pFtp_Server = new CFtp_Server();
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CServer_FTPDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CServer_FTPDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CServer_FTPDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
BOOL CServer_FTPDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
//更改背景颜色
CRect rect;
GetClientRect(&rect);
pDC->FillSolidRect(&rect, RGB(202, 225, 243));
return TRUE;
// return CDialog::OnEraseBkgnd(pDC);
}
void CServer_FTPDlg::OnBtnListen()
{
// TODO: Add your control notification handler code here
if (m_bConnected)
{
m_pFtp_Server->StopListen();
SetDlgItemText(IDC_BTN_LISTEN, _T("启动监听"));
GetDlgItem(IDC_EDIT_PORT)->EnableWindow(TRUE);
m_bConnected = FALSE;
return;
}
CString sPath;
GetDlgItemText(IDC_EDIT_PATH, sPath);
if (sPath.IsEmpty())
{
AfxMessageBox(_T("请先设置文件存储路径!"));
return;
}
int nPort = GetDlgItemInt(IDC_EDIT_PORT);
if (m_pFtp_Server->StartListen(this, nPort, sPath.GetBuffer(0)))
{
SetDlgItemText(IDC_BTN_LISTEN, _T("停止监听"));
GetDlgItem(IDC_EDIT_PORT)->EnableWindow(FALSE);
m_bConnected = TRUE;
return;
}
AfxMessageBox(_T("服务器启动失败!"));
}
void CServer_FTPDlg::OnBtnScan()
{
// TODO: Add your control notification handler code here
BROWSEINFO bi; //定义后面将被SHBrowseForFolder调用参数
char buffer[MAX_PATH];
ZeroMemory(buffer,MAX_PATH);
bi.hwndOwner = this->m_hWnd;
bi.pidlRoot = NULL;
bi.pszDisplayName=buffer;
bi.lpszTitle = "指定文件夹";
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.lParam = 0;
bi.iImage = 0;
LPITEMIDLIST pList = NULL;
if((pList=SHBrowseForFolder(&bi)) != NULL)
{
char path[MAX_PATH];
ZeroMemory(path,MAX_PATH);
SHGetPathFromIDList(pList,path);//根据你设置的属性 打开 返回路径到path
SetDlgItemText(IDC_EDIT_PATH, path);
}
}
void CServer_FTPDlg::InitListColumn()
{
int iWidth = 50;
m_ListFile.InsertColumn(0, "文件名", LVCFMT_LEFT, 3*iWidth, -1);
m_ListFile.InsertColumn(1, "文件大小", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(2, "上传速度", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(3, "上传状态", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(4, "上传时间", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(5, "文件保存路径", LVCFMT_LEFT, 5*iWidth, -1);
m_ListFile.InsertColumn(6, "时间标记", LVCFMT_LEFT, 2*iWidth, -1);
//插入列:左对齐,无子列
m_ListFile.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
}
void CServer_FTPDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
if(m_pFtp_Server != NULL)
{
m_pFtp_Server->StopListen();
delete m_pFtp_Server;
}
}
LRESULT CServer_FTPDlg::OnFileUpdate(WPARAM wp, LPARAM lp)
{
MSGFILESTATUS* pmsg = (MSGFILESTATUS*)wp;
CString strPath;
strPath.Format("%s", pmsg->sFilePath);
int iTotal = m_ListFile.GetItemCount();
int iSel = 0;
for(; iSel<iTotal; iSel++)
{
CString strListPath;
strListPath = m_ListFile.GetItemText(iSel, 5);
if(strPath.Compare(strListPath) == 0)//路径相同
break;
}
if(iSel == iTotal)
return 1;
long lFileLength = m_ListFile.GetItemData(iSel);
CString strStatus;
strStatus.Format("%0.2f%%", (float)pmsg->lFileOffset/lFileLength*100);
//显示状态 %,精确到小数点后两位
m_ListFile.SetItemText(iTotal-1, 3, strStatus.GetBuffer(0));
//显示时间
DWORD dwNowTick, dwStartTick;//毫秒
dwNowTick = GetTickCount();
sscanf(m_ListFile.GetItemText(iSel, 6), "%u", &dwStartTick);
long iEllapsed = (dwNowTick-dwStartTick);//间隔:微秒
strStatus.Format("%dms", iEllapsed);
m_ListFile.SetItemText(iSel, 4, strStatus.GetBuffer(0));
//显示速度
if(iEllapsed > 0)
{
strStatus.Format("%dk/s", (pmsg->lFileOffset/1024/iEllapsed)*1000);
m_ListFile.SetItemText(iSel, 2, strStatus.GetBuffer(0));
}
return 0;
}
LRESULT CServer_FTPDlg::OnFileList(WPARAM wp, LPARAM lp)
{
MSGFILELIST* pmsgList = (MSGFILELIST*)wp;
int iItem = m_ListFile.GetItemCount();
for (int i = m_nUpdateNum; i < iItem; i++)
{
m_ListFile.DeleteItem(i);
}
iItem = m_nUpdateNum;
CString strServerPath, strFileName, strFileSize;
strServerPath.Format("%s", pmsgList->sFilePath);
int iPos = strServerPath.ReverseFind('\\');
//设置文件名到缓冲区
strFileName = strServerPath.Right(strServerPath.GetLength()-iPos-1);
strFileSize.Format("%0.2fk", (float)pmsgList->lFileLength/1024);
LV_ITEM lvi;
lvi.mask = LVIF_TEXT|LVIF_PARAM;
lvi.iItem = iItem;
lvi.iSubItem = 0;
lvi.lParam = pmsgList->lFileLength;
//显示
lvi.pszText
96b1
= strFileName.GetBuffer(0);
m_ListFile.InsertItem(&lvi);
m_ListFile.SetItemText(iItem, 1, strFileSize.GetBuffer(0));
m_ListFile.SetItemText(iItem, 5, strServerPath.GetBuffer(0));
//设置初始时间点
DWORD dwStartTick = GetTickCount();
char sStartTick[20];
sprintf(sStartTick, "%u", dwStartTick);
m_ListFile.SetItemText(iItem, 6, sStartTick);
return 0;
}
LRESULT CServer_FTPDlg::OnFinishUpdate(WPARAM wp, LPARAM lp)
{
++ m_nUpdateNum;
return 0;
}
相关文章推荐
- Java FTP 实现跨服务器文件上传下载
- windows基于阿帕奇+PHP服务器,实现vc++文件上传功能
- java操作ftp实现文件的上传下载(适用于图片文档服务器)
- 用xfire实现从服务器上传和下载文件
- 通过ssh实现服务器文件上传下载
- 利用WebService实现远程服务器文件的上传和下载
- 嵌入式 在arm平台运行ftpd服务器实现文件下载以及上传
- JCIFS实现远程服务器共享文件上传下载
- Java FTP 实现跨服务器文件上传下载
- 【转载】使用jsp实现文件上传到服务器或者从服务器上下载文件到本地计算机完整说明版
- VC实现上传文件到FTP服务器
- 利用WebService实现远程服务器文件的上传和下载
- 实现从svn服务器下载代码,编译成class文件,打成war包后再上传到svn的build文件
- Java实现FTP服务器的上传、下载、删除、查看文件列表
- 利用WebService实现远程服务器文件的上传和下载
- java+jsp代码实现从FTP服务器上传下载文件
- 使用简单的wcf文件实现上传,下载文件到服务器
- windows基于阿帕奇服务器,实现vc++文件下载功能
- Java连接FTP服务器并且实现对其文件的上传和下载
- Java连接FTP服务器并且实现对其文件的上传和下载