FTP服务器与客户端设计与开发.doc
- 文档编号:1216436
- 上传时间:2023-04-30
- 格式:DOC
- 页数:32
- 大小:100KB
FTP服务器与客户端设计与开发.doc
《FTP服务器与客户端设计与开发.doc》由会员分享,可在线阅读,更多相关《FTP服务器与客户端设计与开发.doc(32页珍藏版)》请在冰点文库上搜索。
FTP服务器与客户端设计与开发
详细设计
程序包括5个主要功能:
1.服务器的运行:
启动和停止FTP服务
2.用户管理:
添加用户,删除用户和设置用户权限
3.服务器配置:
设置服务器开放端口,最大连接数等
4.运行统计:
统计当前服务器运行时期上传下载的流量等等
5.安全设置:
允许连接服务器的IP列表,以及禁止访问的IP
服务器的运行模块
功能:
负责FTP服务器的运行。
使用类:
CFTPServer类,CApplicationDlg类,CListenSocket类,CConnectThread类,CConnectSocket类
各种类的功能:
1.CFTPServer类:
是CWnd的子类,作为程序的顶层类,负责实现或者调用各个成员函数
2.CApplicationDlg类:
CDialog类的子类,实现程序主窗口。
3.CListenSocket类:
负责监听FTP客户端连接,并实现有效连接
4.CConnectThread类:
负责实现并保证多个连接的有效性。
5.CConnectSocket类:
实现FTP命令的解析,数据的发送和接收
CFTPServer类
作为服务器的顶层类,实现服务器开始运行时的所有成员函数
申明如下:
classCFTPServer:
publicCWnd
{
friendCConnectSocket;//CConnectSocket作为其友元类,可以访问内部私有数据成员
public:
voidSetGoodbyeMessage(LPCTSTRlpszText);//发送退出信息
voidSetWelcomeMessage(LPCTSTRlpszText);//发送欢迎信息
voidSetTimeout(intnValue);//设置暂停时间
voidSetPort(intnValue);//设置端口
voidSetMaxUsers(intnValue);//设置最大连接数
voidSetStatisticsInterval(intnValue);//统计时间间隔
BOOLIsActive();//是否有效
voidStop();
BOOLStart();
CFTPServer();
virtual~CFTPServer();
CUserManagerm_UserManager;//用户管理对象
CSecurityManagerm_SecurityManager;//安全策略
CFTPServer类
最主要的成员函数是start()和stop(),分别负责ftp服务器的开始运行和结束运行
函数声明如下:
/********************************************************************/
/* */
/*Functionname:
Start */
/*Description:
Startlistiningonport21andacceptnew */
/* connections. */
/* */
/********************************************************************/
BOOLCFTPServer:
:
Start()
{
if(m_bRunning)
returnFALSE;//如果运行,返回错误标志
//createdummywindowformessagerouting
if(!
CWnd:
:
CreateEx(0,AfxRegisterWndClass(0),"FTPServerNotificationSink",WS_POPUP,0,0,0,0,NULL,0))
{
AddTraceLine(0,"Failedtocreatenotificationwindow.");
returnFALSE;
}
//开始创建socket
if(m_ListenSocket.Create(m_nPort))
{
//startlistening
if(m_ListenSocket.Listen())
{
m_ListenSocket.m_pWndServer=this;
m_bRunning=TRUE;
SetTimer(1,m_nStatisticsInterval,NULL);
AddTraceLine(0,"FTPServerstartedonport%d.",m_nPort);
returnTRUE;
}
}
AddTraceLine(0,"FTPServerfailedtolistenonport%d.",m_nPort);
//destroynotificationwindow
if(IsWindow(m_hWnd))
DestroyWindow();
m_hWnd=NULL;
returnFALSE;
}
/********************************************************************/
/* */
/*Functionname:
Stop */
/*Description:
StopFTPserver. */
/* */
/********************************************************************/
voidCFTPServer:
:
Stop()
{
if(!
m_bRunning)
return;
//stopstatisticstimer
KillTimer
(1);
m_bRunning=FALSE;
m_ListenSocket.Close();
CConnectThread*pThread=NULL;
//closeallrunningthreads
do
{
m_CriticalSection.Lock();
POSITIONpos=m_ThreadList.GetHeadPosition();
if(pos!
=NULL)
{
pThread=(CConnectThread*)m_ThreadList.GetAt(pos);
m_CriticalSection.Unlock();
//savethreadmembers
intnThreadID=pThread->m_nThreadID;
HANDLEhThread=pThread->m_hThread;
AddTraceLine(0,"[%d]Shuttingdownthread...",nThreadID);
//tellthreadtostop
pThread->SetThreadPriority(THREAD_PRIORITY_HIGHEST);
pThread->PostThreadMessage(WM_QUIT,0,0);
//waitforthreadtoend,whilekeepingthemessagespumping(max5seconds)
if(WaitWithMessageLoop(hThread,5000)==FALSE)
{
//threaddoesn'twanttostopped
AddTraceLine(0,"[%d]Problemwhilekillingthread.",nThreadID);
//don'ttryagain,soremove
m_CriticalSection.Lock();
POSITIONrmPos=m_ThreadList.Find(pThread);
if(rmPos!
=NULL)
m_ThreadList.RemoveAt(rmPos);
m_CriticalSection.Unlock();
}
else
{
AddTraceLine(0,"[%d]Threadsuccessfullystopped.",nThreadID);
}
}
else
{
m_CriticalSection.Unlock();
pThread=NULL;
}
}
while(pThread!
=NULL);
AddTraceLine(0,"FTPServerstopped.");
if(IsWindow(m_hWnd))
DestroyWindow();
m_hWnd=NULL;
}
CListenSocket类
用于监听每个客户的连接,CListenSocket类是CAsyncSocket的子类,其成员函数listen监听来自客户端的连接,当监听到可以接收的socket的时候通过OnAccept函数准备创建有效连接的进程。
函数如下:
voidCListenSocket:
:
OnAccept(intnErrorCode)
{
//Newconnectionisbeingestablished
CSocketsockit;
//AccepttheconnectionusingatempCSocketobject.
Accept(sockit);
//Createathreadtohandletheconnection.Thethreadiscreatedsuspendedsothatwecan
//setvariablesinCConnectThreadbeforeitstartsexecuting.
CConnectThread*pThread=(CConnectThread*)AfxBeginThread(RUNTIME_CLASS(CConnectThread),THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
if(!
pThread)
{
sockit.Close();
TRACE("Couldnotcreatethread\n");
return;
}
CFTPServer*pWnd=(CFTPServer*)m_pWndServer;
//sinceeverythingissuccessful,addthethreadtoourlist
pWnd->m_CriticalSection.Lock();
pWnd->m_ThreadList.AddTail(pThread);
pWnd->m_CriticalSection.Unlock();
//savepointer
pThread->m_pWndServer=m_pWndServer;
//Passthesockettothethreadbypassingthesockethandle.Youcannotpass
//aCSocketobjectacrossthreads.
pThread->m_hSocket=sockit.Detach();
//Nowstartthethread.
pThread->ResumeThread();
}
CConnectThread类
CConnectThread类负责为每个有效进程创建一个线程,每个进程完成数据传输的所有任务,穿件县城后通过InitInstance完成线程的初始化
BOOLCConnectThread:
:
InitInstance()
{
try
{
//AttachthesockethandletoaCSocketobject.
//Thismakessurethatthesocketnotificationsaresenttothisthread.
m_ConnectSocket.Attach(m_hSocket);
m_ConnectSocket.m_pThread=this;
CStringstrIPAddress;
UINTnPort;
m_ConnectSocket.GetPeerName(strIPAddress,nPort);
//notifyserverthatthere'sanewconnection
m_pWndServer->SendMessage(WM_THREADSTART,(WPARAM)this,0);
if(((CFTPServer*)m_pWndServer)->CheckMaxUsers())
{
m_ConnectSocket.SendResponse("421Toomanyusersareconnected,pleasetryagainlater.");
PostThreadMessage(WM_QUIT,0,0);
}
else
if(!
((CFTPServer*)m_pWndServer)->IsIPAddressAllowed(strIPAddress))
{
m_ConnectSocket.SendResponse("421Accessdenied,IPaddresswasrejectedbytheserver.");
PostThreadMessage(WM_QUIT,0,0);
}
else
{
//sendwelcomemessagetoclient
CStringstrText=((CFTPServer*)m_pWndServer)->GetWelcomeMessage();
m_ConnectSocket.SendResponse("220"+strText);
m_nTimerID=:
:
SetTimer(NULL,0,1000,TimerProc);
}
}
catch(CException*e)
{
e->Delete();
}
returnTRUE;
}
线程结束以后,通过ExitInstance函数实现资源的释放代码如下:
intCConnectThread:
:
ExitInstance()
{
CFTPServer*pWnd=(CFTPServer*)m_pWndServer;
try
{
pWnd->m_CriticalSection.Lock();
//deletethisthreadfromthelinkedlist
POSITIONpos=pWnd->m_ThreadList.Find(this);
if(pos!
=NULL)
{
pWnd->m_ThreadList.RemoveAt(pos);
}
pWnd->m_CriticalSection.Unlock();
//notifyservicemainloop
pWnd->SendMessage(WM_THREADCLOSE,(WPARAM)this,0);
}
catch(CException*e)
{
pWnd->m_CriticalSection.Unlock();
e->Delete();
}
returnCWinThread:
:
ExitInstance();
}
为了了解传输过程中接收和发送的字节数,使用IncReceivedBytes和IncSentBytes来计算。
这两个函数在CConnectSocket类中调用,代码如下:
voidCConnectThread:
:
IncSentBytes(intnBytes)
{
m_LastDataTransferTime=CTime:
:
GetCurrentTime();
m_nSentBytes+=nBytes;
//notifyserverclass
m_pWndServer->PostMessage(WM_THREADMSG,(WPARAM)0,(LPARAM)nBytes);
}
voidCConnectThread:
:
IncReceivedBytes(intnBytes)
{
m_LastDataTransferTime=CTime:
:
GetCurrentTime();
m_nReceivedBytes+=nBytes;
//notifyserverclass
m_pWndServer->PostMessage(WM_THREADMSG,(WPARAM)1,(LPARAM)nBytes);
}
CConnectSocket类
每个线程都是通过一个CConnectSocket对象m_ConnectSocket来完成数据的接受和发送。
当线程创建成功以后,m_ConnectSocket对象通过OnReceive函数获得数据,然后利用ParseCommand函数来解析其中FTP命令
voidCConnectSocket:
:
OnReceive(intnErrorCode)
{
TCHARbuff[BUFFERSIZE];
intnRead=Receive(buff,BUFFERSIZE);
switch(nRead)
{
case0:
Close();
break;
caseSOCKET_ERROR:
if(GetLastError()!
=WSAEWOULDBLOCK)
{
TCHARszError[256];
wsprintf(szError,"OnReceiveerror:
%d",GetLastError());
AfxMessageBox(szError);
}
break;
default:
if(nRead!
=SOCKET_ERROR&&nRead!
=0)
{
((CConnectThread*)AfxGetThread())->IncReceivedBytes(nRead);
//terminatethestring
buff[nRead]=0;
m_RxBuffer+=CString(buff);
GetRxLine();
}
break;
}
CSocket:
:
OnReceive(nErrorCode);
}
ParseCommand函数
是当前程序最重要的一个部分,它根据客户端提交的各种命令进行相应的操作代码如下
voidCConnectSocket:
:
ParseCommand()
{
staticCFTPCommandcommandList[]=
{
{TOK_USER, "USER",TRUE},
{TOK_PASS, "PASS",TRUE},
{TOK_CWD, "CWD", TRUE},
{TOK_PWD, "PWD", FALSE},
{TOK_PORT, "PORT",TRUE},
{TOK_PASV, "PASV",FALSE},
{TOK_TYPE, "TYPE",TRUE},
{TOK_LIST, "LIST",FALSE},
{TOK_REST, "REST",TRUE},
{TOK_CDUP, "CDUP",FALSE},
{TOK_RETR, "RETR",TRUE},
{TOK_STOR, "STOR",TRUE},
{TOK_SIZE, "SIZE",TRUE},
{TOK_DELE, "DELE",TRUE},
{TOK_RMD, "RMD", TRUE},
{TOK_MKD, "MKD", TRUE},
{TOK_RNFR, "RNFR",TRUE},
{TOK_RNTO, "RNTO",TRUE},
{TOK_ABOR, "ABOR",FALSE},
{TOK_SYST, "SYST",FALSE},
{TOK_NOOP, "NOOP",FALSE},
{TOK_BYE, "BYE",FALSE},
{TOK_QUIT, "QUIT",FALSE},
{TOK_ERROR, "", FALSE},
};
//parsecommand
CStringstrCommand,strArguments;
if(!
GetRxCommand(strCommand,strArguments))
{
return;
}
intnCommand;
//查找命令
for(nCommand=TOK_USER;nCommand { //foundcommand? if(strCommand==commandList[nCommand].m_pszName) { //didweexpectanargument? if(commandList[nCommand].m_bHasArguments&&(strArguments=="")) { SendResponse("501Syntaxerror"); return; } break; } } if(nCommand=
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- FTP 服务器 客户端 设计 开发
![提示](https://static.bingdoc.com/images/bang_tan.gif)