📄 server.cpp
字号:
dwBytesLeft -= dwNumOfBytesRead;
}
CloseHandle( hFile );
}
return idx;
}
DWORD CServer::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 CServer::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 CServer::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 CServer::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 CServer::DataRecv( SOCKET s, const char* szFileName )
{
return WriteToFile( s, szFileName );
}
SOCKET CServer::DataAccept( SOCKET& s )
{
SOCKET sAccept = accept( s ,NULL,NULL );
if( sAccept != INVALID_SOCKET )
{
closesocket( s );
}
return sAccept;
}
int CServer::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" );
if( SendRes( pSI ) == -1 )
return -1;
return TRANS_COMPLETE;
}
if( strstr( szCmd,"QUIT" ) )
{
sprintf( pSI->buffSend,"%s","221 Good bye,欢迎下次再来.\r\n" );
if( SendRes( pSI ) == -1 )
return -1;
return FTP_QUIT;
}
if( strstr( szCmd,"XPWD" ) || strstr( szCmd,"PWD") )
{
GetCurrentDirectory( MAX_PATH,szCurrDir );
sprintf( pSI->buffSend,"257 \"%s\" is current directory.\r\n",
RelativeDirectory(szCurrDir) );
if( SendRes( pSI ) == -1 ) return -1;
return CURR_DIR;
}
if( strstr( szCmd,"CWD" ) || strstr(szCmd,"CDUP") )
{
char *szDir = strtok( NULL,"\r\n" );
if( szDir == NULL ) szDir = "\\";
char szSetDir[MAX_PATH];
if( strstr(szCmd,"CDUP") )
strcpy(szSetDir,"..");
else
strcpy(szSetDir,AbsoluteDirectory( szDir ) );
if( !SetCurrentDirectory( szSetDir ) )
{
sprintf(szCurrDir,"\\%s",szSetDir);
sprintf( pSI->buffSend,"550 %s No such file or Directory.\r\n",
RelativeDirectory(szCurrDir) );
nRetVal = CANNOT_FIND;
}
else
{
GetCurrentDirectory( MAX_PATH,szCurrDir );
sprintf( pSI->buffSend,"250 Directory changed to /%s.\r\n",
RelativeDirectory(szCurrDir) );
nRetVal = DIR_CHANGED;
}
if( SendRes( pSI ) == -1 ) return -1;
return nRetVal;
}
if( strstr( szCmd,"SYST" ) )
{
sprintf( pSI->buffSend,"%s","215 Windows_NT Version 4.0\r\n");
if( SendRes( pSI ) == -1 ) return -1;
return OS_TYPE;
}
if( strstr( szCmd,"TYPE") )
{
char *szType = strtok(NULL,"\r\n");
if( szType == NULL ) szType = "A";
sprintf(pSI->buffSend,"200 Type set to %s.\r\n",szType );
if( SendRes( pSI ) == -1 )
return -1;
return CMD_OK;
}
if( strstr( szCmd,"REST" ) )
{
sprintf( pSI->buffSend,"504 Reply marker must be 0.\r\n");
if( SendRes( pSI ) == -1 )
return -1;
return REPLY_MARKER;
}
if( strstr( szCmd,"NOOP") )
{
sprintf( pSI->buffSend,"200 NOOP command successful.\r\n");
if( SendRes( pSI ) == -1 )
return -1;
return CMD_OK;
}
//其余都是无效的命令
sprintf(pSI->buffSend,"500 '%s' command not understand.\r\n",szCmd );
if( SendRes( pSI ) == -1 ) return -1;
return nRetVal;
}
///////////////////////////////////////////////////////////////////////////////////////////
//其他函数
char* CServer::GetLocalAddress()
{
struct in_addr *pinAddr;
LPHOSTENT lpHostEnt;
int nRet;
int nLen;
char szLocalAddr[80];
memset( szLocalAddr,0,sizeof(szLocalAddr) );
// Get our local name
nRet = gethostname(szLocalAddr,sizeof(szLocalAddr) );
if (nRet == SOCKET_ERROR)
{
return NULL;
}
// "Lookup" the local name
lpHostEnt = gethostbyname(szLocalAddr);
if (NULL == lpHostEnt)
{
return NULL;
}
// Format first address in the list
pinAddr = ((LPIN_ADDR)lpHostEnt->h_addr);
nLen = strlen(inet_ntoa(*pinAddr));
if ((DWORD)nLen > sizeof(szLocalAddr))
{
WSASetLastError(WSAEINVAL);
return NULL;
}
return inet_ntoa(*pinAddr);
}
int CServer::GetFileList( LPFILE_INF pFI, UINT nArraySize, const char* szPath )
{
WIN32_FIND_DATA wfd;
int idx = 0;
CHAR lpFileName[MAX_PATH];
GetCurrentDirectory( MAX_PATH,lpFileName );
strcat( lpFileName,"\\" );
strcat( lpFileName, szPath );
HANDLE hFile = FindFirstFile( lpFileName, &wfd );
if ( hFile != INVALID_HANDLE_VALUE )
{
pFI[idx].dwFileAttributes = wfd.dwFileAttributes;
lstrcpy( pFI[idx].szFileName, wfd.cFileName );
pFI[idx].ftCreationTime = wfd.ftCreationTime;
pFI[idx].ftLastAccessTime = wfd.ftLastAccessTime;
pFI[idx].ftLastWriteTime = wfd.ftLastWriteTime;
pFI[idx].nFileSizeHigh = wfd.nFileSizeHigh;
pFI[idx++].nFileSizeLow = wfd.nFileSizeLow;
while( FindNextFile( hFile,&wfd ) && idx < (int)nArraySize )
{
pFI[idx].dwFileAttributes = wfd.dwFileAttributes;
lstrcpy( pFI[idx].szFileName, wfd.cFileName );
pFI[idx].ftCreationTime = wfd.ftCreationTime;
pFI[idx].ftLastAccessTime = wfd.ftLastAccessTime;
pFI[idx].ftLastWriteTime = wfd.ftLastWriteTime;
pFI[idx].nFileSizeHigh = wfd.nFileSizeHigh;
pFI[idx++].nFileSizeLow = wfd.nFileSizeLow;
}
FindClose( hFile );
}
return idx;
}
char* CServer::HostToNet( char* szPath )
{
int idx = 0;
if( NULL == szPath ) return NULL;
strlwr( szPath );
while( szPath[idx] )
{
if( szPath[idx] == '\\' )
szPath[idx] = '/';
idx ++;
}
return szPath;
}
char* CServer::NetToHost( char* szPath )
{
int idx = 0;
if( NULL == szPath ) return NULL;
strlwr( szPath );
while( szPath[idx] )
{
if( '/' == szPath[idx] )
szPath[idx] = '\\';
idx ++;
}
return szPath;
}
char* CServer::RelativeDirectory( char* szDir )
{
int nStrLen = strlen(m_Directory);
if( !strnicmp( szDir,m_Directory, nStrLen ) )
szDir += nStrLen;
if( szDir && szDir[0] == '\0' ) szDir = "/";
return HostToNet(szDir);
}
char* CServer::AbsoluteDirectory( char* szDir )
{
char szTemp[MAX_PATH];
strcpy( szTemp,m_Directory+2 );
if( NULL == szDir ) return NULL;
if( '/' == szDir[0] )
strcat( szTemp, szDir );
szDir = szTemp ;
return NetToHost(szDir);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -