FTPserver部分代码.docx
《FTPserver部分代码.docx》由会员分享,可在线阅读,更多相关《FTPserver部分代码.docx(40页珍藏版)》请在冰豆网上搜索。
FTPserver部分代码
//MiniFtpServer.cpp:
Definestheentrypointfortheconsoleapplication.
#include"stdafx.h"
#include
#include
#include
#defineWSA_RECV0
#defineWSA_SEND1
#defineDATA_BUFSIZE8192
#defineMAX_NAME_LEN128
#defineMAX_PWD_LEN128
#defineMAX_RESP_LEN1024
#defineMAX_REQ_LEN256
#defineMAX_ADDR_LEN80
#defineFTP_PORT21//FTP控制端口
#defineDATA_FTP_PORT20//FTP数据端口
#defineUSER_OK331
#defineLOGGED_IN230
#defineLOGIN_FAILED530
#defineCMD_OK200
#defineOPENING_AMODE150
#defineTRANS_COMPLETE226
#defineCANNOT_FIND550
#defineFTP_QUIT221
#defineCURR_DIR257
#defineDIR_CHANGED250
#defineOS_TYPE215
#defineREPLY_MARKER504
#definePASSIVE_MODE227
#defineFTP_USER"toldo"
#defineFTP_PASS"toldo"
#defineDEFAULT_HOME_DIR"C:
\\TEMP"
#defineMAX_FILE_NUM1024
#defineMODE_PORT0
#defineMODE_PASV1
#definePORT_BIND1821
typedefstruct{
CHARbuffRecv[DATA_BUFSIZE];
CHARbuffSend[DATA_BUFSIZE];
WSABUFwsaBuf;
SOCKETs;
WSAOVERLAPPEDo;
DWORDdwBytesSend;
DWORDdwBytesRecv;
intnStatus;
}SOCKET_INF,*LPSOCKET_INF;
typedefstruct{
TCHARszFileName[MAX_PATH];
DWORDdwFileAttributes;
FILETIMEftCreationTime;
FILETIMEftLastAccessTime;
FILETIMEftLastWriteTime;
DWORDnFileSizeHigh;
DWORDnFileSizeLow;
}FILE_INF,*LPFILE_INF;
DWORDWINAPIProcessTreadIO(LPVOIDlpParam);
BOOLWelcomeInfo(SOCKETs);
intLoginIn(LPSOCKET_INFpSocketInfo);
intSendRes(LPSOCKET_INFpSI);
intRecvReq(LPSOCKET_INFpSI);
intDealCommand(LPSOCKET_INFpSI);
intGetFileList(LPFILE_INFpFI,UINTnArraySize,constchar*szPath);
char*GetLocalAddress();
char*HostToNet(char*szPath);
char*NetToHost(char*szPath);
char*RelativeDirectory(char*szDir);
char*AbsoluteDirectory(char*szDir);
DWORDg_dwEventTotal=0;
DWORDg_index;
WSAEVENTg_events[WSA_MAXIMUM_WAIT_EVENTS];
LPSOCKET_INFg_sockets[WSA_MAXIMUM_WAIT_EVENTS];
CRITICAL_SECTIONg_cs;
charg_szLocalAddr[MAX_ADDR_LEN];
BOOLg_bLoggedIn;
//主函数,控制台程序开始的地方
voidmain(void)
{
WSADATAwsaData;
SOCKETsListen,sAccept;
SOCKADDR_INinetAddr;
DWORDdwFlags;
DWORDdwThreadId;
DWORDdwRecvBytes;
INTnRet;
InitializeCriticalSection(&g_cs);
if((nRet=WSAStartup(0x0202,&wsaData))!
=0){
printf("错误:
WSAStartupfailedwitherror%d\n",nRet);
return;
}
//先取得本地地址
sprintf(g_szLocalAddr,"%s",GetLocalAddress());
if((sListen=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,
WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
{
printf("错误:
Failedtogetasocket%d\n",WSAGetLastError());
WSACleanup();
return;
}
inetAddr.sin_family=AF_INET;
inetAddr.sin_addr.s_addr=htonl(INADDR_ANY);
inetAddr.sin_port=htons(FTP_PORT);
if(bind(sListen,(PSOCKADDR)&inetAddr,sizeof(inetAddr))==SOCKET_ERROR)
{
printf("错误:
bind()failedwitherror%d\n",WSAGetLastError());
return;
}
if(listen(sListen,SOMAXCONN))
{
printf("错误:
listen()failedwitherror%d\n",WSAGetLastError());
return;
}
printf("MiniFtpserver已经启动\n");
printf("MiniFtpserver开始侦听\n");
if((sAccept=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,
WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
{
printf("错误:
Failedtogetasocket%d\n",WSAGetLastError());
return;
}
//创建第一个手动重置对象
if((g_events[0]=WSACreateEvent())==WSA_INVALID_EVENT)
{
printf("错误:
WSACreateEventfailedwitherror%d\n",WSAGetLastError());
return;
}
//创建一个线程处理请求
if(CreateThread(NULL,0,ProcessTreadIO,NULL,0,&dwThreadId)==NULL)
{
printf("错误:
CreateThreadfailedwitherror%d\n",GetLastError());
return;
}
g_dwEventTotal=1;
while(TRUE)
{
//处理入站连接
if((sAccept=accept(sListen,NULL,NULL))==INVALID_SOCKET)
{
printf("错误:
acceptfailedwitherror%d\n",WSAGetLastError());
return;
}
//回传欢迎消息
if(!
WelcomeInfo(sAccept))break;
//设置ftp根目录
if(!
SetCurrentDirectory(DEFAULT_HOME_DIR))break;
//操作临界区,防止出错
EnterCriticalSection(&g_cs);
//创建一个新的SOCKET_INF结构处理接受的数据socket.
if((g_sockets[g_dwEventTotal]=(LPSOCKET_INF)
GlobalAlloc(GPTR,sizeof(SOCKET_INF)))==NULL)
{
printf("错误:
GlobalAlloc()failedwitherror%d\n",GetLastError());
return;
}
//初始化新的SOCKET_INF结构
charbuff[DATA_BUFSIZE];memset(buff,0,DATA_BUFSIZE);
g_sockets[g_dwEventTotal]->wsaBuf.buf=buff;
g_sockets[g_dwEventTotal]->wsaBuf.len=DATA_BUFSIZE;
g_sockets[g_dwEventTotal]->s=sAccept;
memset(&(g_sockets[g_dwEventTotal]->o),0,sizeof(OVERLAPPED));
g_sockets[g_dwEventTotal]->dwBytesSend=0;
g_sockets[g_dwEventTotal]->dwBytesRecv=0;
g_sockets[g_dwEventTotal]->nStatus=WSA_RECV;//接收
//创建事件
if((g_sockets[g_dwEventTotal]->o.hEvent=g_events[g_dwEventTotal]=
WSACreateEvent())==WSA_INVALID_EVENT)
{
printf("WSACreateEvent()failedwitherror%d\n",WSAGetLastError());
return;
}
//发出接受请求
dwFlags=0;
if(WSARecv(g_sockets[g_dwEventTotal]->s,
&(g_sockets[g_dwEventTotal]->wsaBuf),1,&dwRecvBytes,&dwFlags,
&(g_sockets[g_dwEventTotal]->o),NULL)==SOCKET_ERROR)
{
if(WSAGetLastError()!
=ERROR_IO_PENDING)
{
printf("错误:
WSARecv()failedwitherror%d\n",WSAGetLastError());
return;
}
}
g_dwEventTotal++;
//离开临界区
LeaveCriticalSection(&g_cs);
//使第一个事件有信号。
使工作者线程处理其他的事件
if(WSASetEvent(g_events[0])==FALSE)
{
printf("错误:
WSASetEventfailedwitherror%d\n",WSAGetLastError());
return;
}
}
}
//工作者线程处理函数
DWORDWINAPIProcessTreadIO(LPVOIDlpParameter)
{
DWORDdwFlags;
LPSOCKET_INFpSI;
DWORDdwBytesTransferred;
DWORDi;
//处理异步的WSASend,WSARecv等请求等
while(TRUE)
{
if((g_index=WSAWaitForMultipleEvents(g_dwEventTotal,g_events,FALSE,
WSA_INFINITE,FALSE))==WSA_WAIT_FAILED)
{
printf("错误:
WSAWaitForMultipleEventsfailed%d\n",WSAGetLastError());
return0;
}
if((g_index-WSA_WAIT_EVENT_0)==0)
{
WSAResetEvent(g_events[0]);
continue;
}
pSI=g_sockets[g_index-WSA_WAIT_EVENT_0];
WSAResetEvent(g_events[g_index-WSA_WAIT_EVENT_0]);
if(WSAGetOverlappedResult(pSI->s,&(pSI->o),&dwBytesTransferred,
FALSE,&dwFlags)==FALSE||dwBytesTransferred==0)
{
printf("Closingsocket%d\n",pSI->s);
if(closesocket(pSI->s)==SOCKET_ERROR)
{
printf("错误:
closesocket()failedwitherror%d\n",WSAGetLastError());
}
GlobalFree(pSI);
WSACloseEvent(g_events[g_index-WSA_WAIT_EVENT_0]);
//Cleanupg_socketsandg_eventsbyremovingthesocketeventhandle
//andsocketinformationstructureiftheyarenotattheendofthe
//arrays.
EnterCriticalSection(&g_cs);
if((g_index-WSA_WAIT_EVENT_0)+1!
=g_dwEventTotal)
for(i=g_index-WSA_WAIT_EVENT_0;i{
g_events[i]=g_events[i+1];
g_sockets[i]=g_sockets[i+1];
}
g_dwEventTotal--;
LeaveCriticalSection(&g_cs);
continue;
}
//已经有数据传递
if(pSI->nStatus==WSA_RECV)
{
memcpy(&pSI->buffRecv[pSI->dwBytesRecv],pSI->wsaBuf.buf,dwBytesTransferred);
pSI->dwBytesRecv+=dwBytesTransferred;
printf("接受:
%s\n",pSI->buffRecv);
if(pSI->buffRecv[pSI->dwBytesRecv-2]=='\r'//要保证最后是\r\n
&&pSI->buffRecv[pSI->dwBytesRecv-1]=='\n'
&&pSI->dwBytesRecv>2)
{
if(!
g_bLoggedIn)
{
if(LoginIn(pSI)==LOGGED_IN)
g_bLoggedIn=TRUE;
}
else
{
if(DealCommand(pSI)==FTP_QUIT)
continue;
}
//缓冲区清除
memset(pSI->buffRecv,0,sizeof(pSI->buffRecv));
pSI->dwBytesRecv=0;
}
}
else
{
pSI->dwBytesSend+=dwBytesTransferred;
}
//继续接收以后到来的数据
if(RecvReq(pSI)==-1)
return-1;
}
return0;
}
//由于只是简单的出现一个登录信息,直接用send就可以了
intSendRes(LPSOCKET_INFpSI)
{
staticDWORDdwSendBytes=0;
pSI->nStatus=WSA_SEND;
memset(&(pSI->o),0,sizeof(WSAOVERLAPPED));
pSI->o.hEvent=g_events[g_index-WSA_WAIT_EVENT_0];
pSI->wsaBuf.buf=pSI->buffSend+pSI->dwBytesSend;
pSI->wsaBuf.len=strlen(pSI->buffSend)-pSI->dwBytesSend;
if(WSASend(pSI->s,&(pSI->wsaBuf),1,&dwSendBytes,
0,&(pSI->o),NULL)==SOCKET_ERROR)
{
if(WSAGetLastError()!
=ERROR_IO_PENDING)
{
printf("WSASend()failedwitherror%d\n",WSAGetLastError());
return-1;
}
}
return0;
}
//接受数据
intRecvReq(LPSOCKET_INFpSI)
{
staticDWORDdwRecvBytes=0;
pSI->nStatus=WSA_RECV;
DWORDdwFlags=0;
memset(&(pSI->o),0,sizeof(WSAOVERLAPPED));
pSI->o.hEvent=g_events[g_index-WSA_WAIT_EVENT_0];
pSI->wsaBuf.len=DATA_BUFSIZE;
if(WSARecv(pSI->s,&(pSI->wsaBuf),1,&dwRecvBytes,
&dwFlags,&(pSI->o),NULL)==SOCKET_ERROR)
{
if(WSAGetLastError()!
=ERROR_IO_PENDING)
{
printf("WSARecv()failedwitherror%d\n",WSAGetLastError());
return-1;
}
}
return0;
}
//显示欢迎消息
BOOLWelcomeInfo(SOCKETs)
{
char*szWelcomeInfo="220欢迎您登录到MiniFtpServer...\r\n";
if(send(s,szWelcomeInfo,strlen(szWelcomeInfo),0)==SOCKET_ERROR)
{
printf("Ftpclienterror:
%d\n",WSAGetLastError());
returnFALSE;
}
//刚进来,还没连接,故设置初始状态为false
g_bLoggedIn=FALSE;
returnTRUE;
}
//登录函数
intLoginIn(LPSOCKET_INFpSocketInfo)
{
constchar*szUserOK="331Usernameokay,needpassword.\r\n";
constchar*szLoggedIn="230Userloggedin,proceed.\r\n";
intnRetVal=0;
staticcharszUser[MAX_NAME_LEN],szPwd[MAX_PWD_LEN];
LPSOCKET_INFpSI=pSocketInfo;
//取得登录用户名
if(strstr(strupr(pSI->buffRecv),"USER"))
{
sprintf(szUser,"%s",pSI->buffRecv+strlen("USER")+1);
strtok(szUser,"\r\n");
//响应信息
sprintf(pSI->buffSend,"%s",szUserOK);
if(SendRes(pSI)==-1)return-1;
returnUSER_OK;
}
if(strstr(strupr(pSI->buffRecv),"PASS")||strstr(pSI->buffRecv,"pass"))
{
sprintf(szPwd,"%s",pSI->buffRecv+strlen("PASS")+1);
strtok(szPwd,"\r\n");
//判断用户名跟口令正确性
if(stricmp(szPwd,FTP_USER)||stricmp(szUser,FTP_PASS))
{
sprintf(pSI->buffSend,"530User%s