FTP服务器端源代码:
// Mini FtpServer.cpp : Defines the entry point for the console application. #include "stdafx.h"
#include
#include
#include
#pragma comment(lib,”ws2_32.lib”);
#define WSA_RECV 0
#define WSA_SEND 1
#define DATA_BUFSIZE 8192
#define MAX_NAME_LEN 128
#define MAX_PWD_LEN 128
#define MAX_RESP_LEN 1024
#define MAX_REQ_LEN 256
#define MAX_ADDR_LEN 80
#define FTP_PORT 21 // FTP 控制端口
#define DATA_FTP_PORT 20 // FTP 数据端口
#define USER_OK 331
#define LOGGED_IN 230
#define LOGIN_FAILED 530
#define CMD_OK 200
#define OPENING_AMODE 150
#define TRANS_COMPLETE 226
#define CANNOT_FIND 550
#define FTP_QUIT 221
#define CURR_DIR 257
#define DIR_CHANGED 250
#define OS_TYPE 215
#define REPLY_MARKER 504
#define PASSIVE_MODE 227
#define FTP_USER "toldo"
#define FTP_PASS "toldo"
#define DEFAULT_HOME_DIR "C:\\TEMP"
#define MAX_FILE_NUM 1024
#define MODE_PORT 0
#define MODE_PASV 1
#define PORT_BIND 1821
typedef struct {
CHAR buffRecv[DATA_BUFSIZE];
CHAR buffSend[DATA_BUFSIZE];
WSABUF wsaBuf;
SOCKET s;
WSAOVERLAPPED o;
DWORD dwBytesSend;
DWORD dwBytesRecv;
int nStatus;
} SOCKET_INF, *LPSOCKET_INF;
typedef struct {
TCHAR szFileName[MAX_PATH];
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
} FILE_INF, *LPFILE_INF;
DWORD WINAPI ProcessTreadIO( LPVOID lpParam ) ;
BOOL WelcomeInfo( SOCKET s );
int LoginIn( LPSOCKET_INF pSocketInfo );
int SendRes( LPSOCKET_INF pSI );
int RecvReq( LPSOCKET_INF pSI );
int DealCommand( LPSOCKET_INF pSI );
int GetFileList( LPFILE_INF pFI, UINT nArraySize, const char* szPath ); char* GetLocalAddress();
char* HostToNet( char* szPath ) ;
char* NetToHost( char* szPath ) ;
char* RelativeDirectory( char* szDir );
char* AbsoluteDirectory( char* szDir );
DWORD g_dwEventTotal = 0;
DWORD g_index;
WSAEVENT g_events[WSA_MAXIMUM_WAIT_EVENTS]; LPSOCKET_INF g_sockets[WSA_MAXIMUM_WAIT_EVENTS]; CRITICAL_SECTION g_cs;
char g_szLocalAddr[MAX_ADDR_LEN];
BOOL g_bLoggedIn;
// 主函数,控制台程序开始的地方
void main(void)
{
WSADATA wsaData;
SOCKET sListen, sAccept;
SOCKADDR_IN inetAddr;
DWORD dwFlags;
DWORD dwThreadId;
DWORD dwRecvBytes;
INT nRet;
InitializeCriticalSection(&g_cs);
if (( nRet = WSAStartup(0x0202,&wsaData)) != 0 ) {
printf("错误:WSAStartup failed with error %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("错误:Failed to get a socket %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() failed with error %d\n", WSAGetLastError());
return;
}
if (listen(sListen, SOMAXCONN))
{
printf("错误:listen() failed with error %d\n", WSAGetLastError());
return;
}
printf("Mini Ftpserver已经启动\n");
printf("Mini Ftpserver开始侦听\n");
if ((sAccept = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("错误:Failed to get a socket %d\n", WSAGetLastError());
return;
}
//创建第一个手动重置对象
if ((g_events[0] = WSACreateEvent()) == WSA_INVALID_EVENT)
{
printf("错误:WSACreateEvent failed with error %d\n", WSAGetLastError());
return;
}
// 创建一个线程处理请求
if (CreateThread(NULL, 0, ProcessTreadIO, NULL, 0, &dwThreadId) == NULL) {
printf("错误:CreateThread failed with error %d\n", GetLastError());
return;
}
g_dwEventTotal = 1;
while(TRUE)
{
//处理入站连接
if ((sAccept = accept(sListen, NULL, NULL)) == INVALID_SOCKET)
{
printf("错误:accept failed with error %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() failed with error %d\n", GetLastError());
return;
}
//初始化新的SOCKET_INF结构
char buff[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() failed with error %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() failed with error %d\n", WSAGetLastError());
return;
}
}
g_dwEventTotal++;
//离开临界区
LeaveCriticalSection(&g_cs);
//使第一个事件有信号。使工作者线程处理其他的事件
if (WSASetEvent(g_events[0]) == FALSE)
{
printf("错误:WSASetEvent failed with error %d\n", WSAGetLastError());
return;
}
}
}
//工作者线程处理函数
DWORD WINAPI ProcessTreadIO(LPVOID lpParameter)
{
DWORD dwFlags;
LPSOCKET_INF pSI;
DWORD dwBytesTransferred;
DWORD i;
//处理异步的WSASend, WSARecv等请求等
while(TRUE)
{
if ((g_index = WSAWaitForMultipleEvents(g_dwEventTotal, g_events, FALSE,
WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) {
printf("错误:WSAWaitForMultipleEvents failed %d\n", WSAGetLastError());
return 0;
}
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("Closing socket %d\n", pSI->s);
if (closesocket(pSI->s) == SOCKET_ERROR)
{
printf("错误:closesocket() failed with error %d\n", WSAGetLastError());
}
GlobalFree(pSI);
WSACloseEvent(g_events[g_index - WSA_WAIT_EVENT_0]);
// Cleanup g_sockets and g_events by removing the socket event handle
// and socket information structure if they are not at the end of the
// arrays.
EnterCriticalSection(&g_cs);
if ((g_index - WSA_WAIT_EVENT_0) + 1 != g_dwEventTotal)
for (i = g_index - WSA_WAIT_EVENT_0; i < g_dwEventTotal; 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;
}
return 0;
}
// 由于只是简单的出现一个登录信息,直接用send就可以了
int SendRes( LPSOCKET_INF pSI )
{
static DWORD dwSendBytes = 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() failed with error %d\n", WSAGetLastError());
return -1;
}
}
return 0;
}
//接受数据
int RecvReq( LPSOCKET_INF pSI )
{
static DWORD dwRecvBytes = 0;
pSI->nStatus = WSA_RECV;
DWORD dwFlags = 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() failed with error %d\n", WSAGetLastError());
return -1;
}
}
return 0;
}
//显示欢迎消息
BOOL WelcomeInfo( SOCKET s )
{
char* szWelcomeInfo = "220 欢迎您登录到Mini FtpServer...\r\n";
if( send( s,szWelcomeInfo,strlen(szWelcomeInfo),0 ) == SOCKET_ERROR ) {
printf("Ftp client error:%d\n", WSAGetLastError() );
return FALSE;
}
// 刚进来,还没连接,故设置初始状态为false
g_bLoggedIn = FALSE;
return TRUE;
}
//登录函数
int LoginIn( LPSOCKET_INF pSocketInfo )
{
const char* szUserOK = "331 User name okay, need password.\r\n";
const char* szLoggedIn = "230 User logged in, proceed.\r\n";
int nRetVal = 0;
static char szUser[MAX_NAME_LEN], szPwd[MAX_PWD_LEN];
LPSOCKET_INF pSI = 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;
return USER_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,"530 User %s cannot log in.\r\n",szUser );
printf("User %s cannot log in\n",szUser );
nRetVal = LOGIN_FAILED;
}
else
{
sprintf(pSI->buffSend,"%s",szLoggedIn);
printf("User %s logged in\n",szUser );
nRetVal = LOGGED_IN;
}
if( SendRes( pSI ) == -1 )
return -1;
}
return nRetVal;
}
char* ConvertCommaAddress( char* szAddress, WORD wPort )
{
char szPort[10];
sprintf( szPort,"%d,%d",wPort/256,wPort%256 );
char szIpAddr[20];
sprintf( szIpAddr,"%s,",szAddress );
int idx = 0;
while( szIpAddr[idx] )
{
if( szIpAddr[idx] == '.' )
szIpAddr[idx] = ',';
idx ++;
}
sprintf( szAddress,"%s%s",szIpAddr,szPort );
return szAddress;
}
int ConvertDotAddress( char* szAddress, LPDWORD pdwIpAddr, LPWORD pwPort ) {
int idx = 0,i = 0, iCount = 0;
char szIpAddr[MAX_ADDR_LEN]; memset( szIpAddr,0,sizeof(szIpAddr) );
char szPort[MAX_ADDR_LEN]; memset( szPort,0, sizeof(szPort) );
*pdwIpAddr = 0; *pwPort = 0;
while( szAddress[idx] )
{
if( szAddress[idx] == ',' )
{
iCount ++;
szAddress[idx] ='.';
}
if( iCount < 4 )
szIpAddr[idx] = szAddress[idx];
else
szPort[i++] = szAddress[idx];
idx++;
}
if( iCount != 5 ) return -1;
*pdwIpAddr = inet_addr( szIpAddr );
if( *pdwIpAddr == INADDR_NONE ) return -1;
char *pToken = strtok( szPort+1,"." );
if( pToken == NULL ) return -1;
*pwPort = (WORD)(atoi(pToken) * 256);
pToken = strtok(NULL,".");
if( pToken == NULL ) return -1;
*pwPort += (WORD)atoi(pToken);
return 0;
}
UINT FileListToString( char* buff, UINT nBuffSize,BOOL bDetails )
{
FILE_INF fi[MAX_FILE_NUM];
int nFiles = GetFileList( fi, MAX_FILE_NUM, "*.*" );
char szTemp[128];
sprintf( buff,"%s","" );
if( bDetails ) {
for( int i=0; i if( strlen(buff)>nBuffSize-128 ) break; if(!strcmp(fi[i].szFileName,".")) continue; if(!strcmp(fi[i].szFileName,"..")) continue; // 时间 SYSTEMTIME st; FileTimeToSystemTime(&(fi[i].ftLastWriteTime), &st); char *szNoon = "AM"; if( st.wHour > 12 ) { st.wHour -= 12; szNoon = "PM"; } if( st.wYear >= 2000 ) st.wYear -= 2000; else st.wYear -= 1900; sprintf( szTemp,"%02u-%02u-%02u %02u:%02u%s ", st.wMonth,st.wDay,st.wYear,st.wHour,st.wMonth,szNoon ); strcat( buff,szTemp ); if( fi[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { strcat(buff,"
strcat(buff," ");
}
else
{
strcat(buff," ");
// 文件大小
sprintf( szTemp,"% 9d ",fi[i].nFileSizeLow );
strcat( buff,szTemp );
}
// 文件名
strcat( buff,fi[i].szFileName );
strcat( buff,"\r\n");
}
}
else
{
for( int i=0; i { if( strlen(buff) + strlen( fi[i].szFileName ) + 2 < nBuffSize ) { strcat( buff, fi[i].szFileName ); strcat( buff, "\r\n"); } else break; } } return strlen( buff ); } DWORD ReadFileToBuffer( const char* szFile, char *buff, DWORD nFileSize ) { DWORD idx = 0; DWORD dwBytesLeft = nFileSize; DWORD dwNumOfBytesRead = 0; char lpFileName[MAX_PATH]; GetCurrentDirectory( MAX_PATH,lpFileName ); strcat( lpFileName,"\\" ); strcat(lpFileName,szFile ); HANDLE hFile = CreateFile( lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile != INVALID_HANDLE_VALUE ) { while( dwBytesLeft > 0 ) { if( !ReadFile( hFile,&buff[idx],dwBytesLeft,&dwNumOfBytesRead,NULL ) ) { printf("读文件出错.\n"); CloseHandle( hFile ); return 0; } idx += dwNumOfBytesRead; dwBytesLeft -= dwNumOfBytesRead; } CloseHandle( hFile ); } return idx; } DWORD WriteToFile( SOCKET s , const char* szFile ) { DWORD idx = 0; DWORD dwNumOfBytesWritten = 0; DWORD nBytesLeft = DATA_BUFSIZE; char buf[DATA_BUFSIZE]; char lpFileName[MAX_PATH]; GetCurrentDirectory( MAX_PATH,lpFileName ); strcat( lpFileName,"\\" ); strcat(lpFileName,szFile ); HANDLE hFile = CreateFile( lpFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { printf("打开文件出错.\n"); return 0; } while( TRUE ) { int nBytesRecv = 0; idx = 0; nBytesLeft = DATA_BUFSIZE; while( nBytesLeft > 0 ) { nBytesRecv = recv( s,&buf[idx],nBytesLeft,0 ); if( nBytesRecv == SOCKET_ERROR ) { printf("Failed to send buffer to socket %d\n",WSAGetLastError() ); return -1; } if( nBytesRecv == 0 ) break; idx += nBytesRecv; nBytesLeft -= nBytesRecv; } nBytesLeft = idx; // 要写入文件中的字节数 idx = 0; // 索引清0,指向开始位置 while( nBytesLeft > 0 ) { // 移动文件指针到文件末尾 if( !SetEndOfFile(hFile) ) return 0; if( !WriteFile( hFile,&buf[idx],nBytesLeft,&dwNumOfBytesWritten,NULL ) ) { printf("写文件出错.\n"); CloseHandle( hFile ); return 0; } idx += dwNumOfBytesWritten; nBytesLeft -= dwNumOfBytesWritten; } // 如果没有数据可接收,退出循环 if( nBytesRecv == 0 ) break; } CloseHandle( hFile ); return idx; } int CombindFileNameSize( const char* szFileName,char* szFileNS ) { // 假定文件的大小不超过4GB,只处理低位 int nFileSize = -1; FILE_INF fi[1]; int nFiles = GetFileList( fi,1,szFileName ); if( nFiles != 1 ) return -1; sprintf( szFileNS, "%s<%d bytes>",szFileName,fi[0].nFileSizeLow ); nFileSize = fi[0].nFileSizeLow; return nFileSize; } int DataConn( SOCKET& s, DWORD dwIp, WORD wPort, int nMode ) { // 创建一个socket s = socket( AF_INET,SOCK_STREAM,0 ); if( s == INVALID_SOCKET ) { printf("Failed to get a socket %d\n", WSAGetLastError()); return -1; } struct sockaddr_in inetAddr; inetAddr.sin_family = AF_INET; if( nMode == MODE_PASV ) { inetAddr.sin_port = htons( wPort ); inetAddr.sin_addr.s_addr = dwIp; } else { inetAddr.sin_port = htons( DATA_FTP_PORT ); inetAddr.sin_addr.s_addr = inet_addr(GetLocalAddress()); } BOOL optval = TRUE; if( setsockopt(s,SOL_SOCKET,SO_REUSEADDR, (char*)&optval,sizeof(optval) ) == SOCKET_ERROR ) { printf("Failed to setsockopt %d.\n",WSAGetLastError() ); closesocket(s); return -1; } if( bind( s,(struct sockaddr*)&inetAddr,sizeof(inetAddr)) == SOCKET_ERROR ) { printf("Failed to bind a socket %d.\n",WSAGetLastError() ); closesocket(s); return -1; } if( MODE_PASV == nMode ) { if( listen( s,SOMAXCONN ) == SOCKET_ERROR ) { printf("Failed to listen a socket %d.\n",WSAGetLastError() ); closesocket(s); return -1; } } else if( MODE_PORT == nMode ) { struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons( wPort ); addr.sin_addr.s_addr = dwIp; if( connect( s, (const sockaddr*)&addr,sizeof(addr) ) == SOCKET_ERROR ) { printf("Failed to connect a socket %d\n",WSAGetLastError() ); closesocket( s ); return -1; } } return 0; } int DataSend( SOCKET s, char* buff,int nBufSize ) { int nBytesLeft = nBufSize; int idx = 0, nBytes = 0; while( nBytesLeft > 0 ) { nBytes = send( s,&buff[idx],nBytesLeft,0); if( nBytes == SOCKET_ERROR ) { printf("Failed to send buffer to socket %d\n",WSAGetLastError() ); closesocket( s ); return -1; } nBytesLeft -= nBytes; idx += nBytes; } return idx; } int DataRecv( SOCKET s, const char* szFileName ) { return WriteToFile( s, szFileName ); } SOCKET DataAccept( SOCKET& s ) { SOCKET sAccept = accept( s ,NULL,NULL ); if( sAccept != INVALID_SOCKET ) { closesocket( s ); } return sAccept; } int DealCommand( LPSOCKET_INF pSI ) { int nRetVal = 0; static SOCKET sAccept = INVALID_SOCKET; static SOCKET s = INVALID_SOCKET; static BOOL bPasv = FALSE; char szCmd[MAX_REQ_LEN]; char szCurrDir[MAX_PATH]; strcpy( szCmd, pSI->buffRecv ); if( strtok( szCmd," \r\n") == NULL ) return -1; strupr( szCmd ); const char* szOpeningAMode = "150 Opening ASCII mode data connection for "; static DWORD dwIpAddr = 0; static WORD wPort = 0; // ?PORT n1,n2,n3,n4,n5,n6 if( strstr(szCmd,"PORT") ) { if( ConvertDotAddress( pSI->buffRecv+strlen("PORT")+1,&dwIpAddr,&wPort) == -1 ) return -1; const char* szPortCmdOK = "200 PORT Command successful.\r\n"; sprintf(pSI->buffSend,"%s",szPortCmdOK ); if( SendRes( pSI ) == -1 ) return -1; bPasv = FALSE; return CMD_OK; } if( strstr( szCmd,"PASV") ) { if( DataConn( s, htonl(INADDR_ANY), PORT_BIND, MODE_PASV ) == -1 ) return -1; char *szCommaAddress = ConvertCommaAddress( GetLocalAddress(),PORT_BIND ); sprintf( pSI->buffSend,"227 Entering Passive Mode (%s).\r\n",szCommaAddress ); if( SendRes( pSI ) == -1 ) return -1; bPasv = TRUE; return PASSIVE_MODE; } if( strstr( szCmd, "NLST") || strstr( szCmd,"LIST") ) { if( bPasv ) sAccept = DataAccept( s ); if( !bPasv ) sprintf(pSI->buffSend,"%s/bin/ls.\r\n",szOpeningAMode ); else strcpy(pSI->buffSend,"125 Data connection already open; Transfer starting.\r\n"); if( SendRes( pSI ) == -1 ) return -1; // 取得文件列表信息,并转换成字符串 BOOL bDetails = strstr(szCmd,"LIST")?TRUE:FALSE; char buff[DATA_BUFSIZE]; UINT nStrLen = FileListToString( buff,sizeof(buff),bDetails); if( !bPasv ) { if( DataConn( s,dwIpAddr,wPort,MODE_PORT ) == -1 ) return -1; if( DataSend( s, buff,nStrLen ) == -1 ) return -1; closesocket(s); } else { DataSend( sAccept,buff,nStrLen ); closesocket( sAccept ); } sprintf( pSI->buffSend,"%s","226 Transfer complete.\r\n" ); if( SendRes( pSI ) == -1 ) return -1; return TRANS_COMPLETE; } if( strstr( szCmd, "RETR") ) { if( bPasv ) sAccept = DataAccept(s); char szFileNS[MAX_PATH]; char *szFile = strtok( NULL," \r\n" ); int nFileSize = CombindFileNameSize( szFile,szFileNS ); if( nFileSize == -1 ) { sprintf( pSI->buffSend,"550 %s: 系统找不到指定的文件.\r\n",szFile); if( SendRes( pSI ) == -1 ) return -1; if( !bPasv ) closesocket( sAccept ); else closesocket( s ); return CANNOT_FIND; } else sprintf(pSI->buffSend,"%s%s.\r\n",szOpeningAMode,szFileNS); if( SendRes( pSI ) == -1 ) return -1; char* buff = new char[nFileSize]; if( NULL ==buff ) { printf("Not enough memory error!\n"); return -1; } if( ReadFileToBuffer( szFile,buff, nFileSize ) == (DWORD)nFileSize ) { // 处理Data FTP连接 Sleep( 10 ); if( bPasv ) { DataSend( sAccept,buff,nFileSize ); closesocket( sAccept ); } else { if( DataConn( s,dwIpAddr,wPort,MODE_PORT ) == -1 ) return -1; DataSend( s, buff, nFileSize ); closesocket( s ); } } if( buff != NULL ) delete[] buff; sprintf( pSI->buffSend,"%s","226 Transfer complete.\r\n" ); if( SendRes( pSI ) == -1 ) return -1; return TRANS_COMPLETE; } if( strstr( szCmd, "STOR") ) { if( bPasv ) sAccept = DataAccept(s); char *szFile = strtok( NULL," \r\n" ); if( NULL == szFile ) return -1; sprintf(pSI->buffSend,"%s%s.\r\n",szOpeningAMode,szFile); if( SendRes( pSI ) == -1 ) return -1; // 处理Data FTP连接 if( bPasv ) DataRecv( sAccept,szFile ); else { if( DataConn( s,dwIpAddr,wPort,MODE_PORT ) == -1 ) return -1; DataRecv( s, szFile ); } sprintf( pSI->buffSend,"%s","226 Transfer complete.\r\n" );