FTP服务器源代码C语言.doc_第1页
FTP服务器源代码C语言.doc_第2页
FTP服务器源代码C语言.doc_第3页
FTP服务器源代码C语言.doc_第4页
FTP服务器源代码C语言.doc_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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_USERtoldo#define FTP_PASStoldo#define DEFAULT_HOME_DIR C:TEMP#define MAX_FILE_NUM 1024#define MODE_PORT 0#define MODE_PASV 1#define PORT_BIND 1821typedef struct CHAR buffRecvDATA_BUFSIZE; CHAR buffSendDATA_BUFSIZE; WSABUF wsaBuf; SOCKET s; WSAOVERLAPPED o; DWORD dwBytesSend; DWORD dwBytesRecv; int nStatus; SOCKET_INF, *LPSOCKET_INF;typedef struct TCHAR szFileNameMAX_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_eventsWSA_MAXIMUM_WAIT_EVENTS;LPSOCKET_INF g_socketsWSA_MAXIMUM_WAIT_EVENTS;CRITICAL_SECTION g_cs; char g_szLocalAddrMAX_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 %dn, 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 %dn, 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 %dn, WSAGetLastError(); return; if (listen(sListen, SOMAXCONN) printf(错误:listen() failed with error %dn, 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 %dn, WSAGetLastError(); return; /创建第一个手动重置对象 if (g_events0 = WSACreateEvent() = WSA_INVALID_EVENT) printf(错误:WSACreateEvent failed with error %dn, WSAGetLastError(); return; / 创建一个线程处理请求 if (CreateThread(NULL, 0, ProcessTreadIO, NULL, 0, &dwThreadId) = NULL) printf(错误:CreateThread failed with error %dn, GetLastError(); return; g_dwEventTotal = 1; while(TRUE) /处理入站连接 if (sAccept = accept(sListen, NULL, NULL) = INVALID_SOCKET) printf(错误:accept failed with error %dn, WSAGetLastError(); return; /回传欢迎消息 if( !WelcomeInfo( sAccept ) ) break; /设置ftp根目录 if( !SetCurrentDirectory( DEFAULT_HOME_DIR ) ) break; /操作临界区,防止出错 EnterCriticalSection(&g_cs); /创建一个新的SOCKET_INF结构处理接受的数据socket. if (g_socketsg_dwEventTotal = (LPSOCKET_INF) GlobalAlloc(GPTR,sizeof(SOCKET_INF) = NULL) printf(错误:GlobalAlloc() failed with error %dn, GetLastError(); return; /初始化新的SOCKET_INF结构 char buffDATA_BUFSIZE; memset( buff,0,DATA_BUFSIZE ); g_socketsg_dwEventTotal-wsaBuf.buf = buff; g_socketsg_dwEventTotal-wsaBuf.len = DATA_BUFSIZE; g_socketsg_dwEventTotal-s = sAccept; memset(&(g_socketsg_dwEventTotal-o),0, sizeof(OVERLAPPED); g_socketsg_dwEventTotal-dwBytesSend = 0; g_socketsg_dwEventTotal-dwBytesRecv = 0; g_socketsg_dwEventTotal-nStatus = WSA_RECV; / 接收 /创建事件 if (g_socketsg_dwEventTotal-o.hEvent = g_eventsg_dwEventTotal = WSACreateEvent() = WSA_INVALID_EVENT) printf(WSACreateEvent() failed with error %dn, WSAGetLastError(); return; /发出接受请求 dwFlags = 0; if (WSARecv(g_socketsg_dwEventTotal-s, &(g_socketsg_dwEventTotal-wsaBuf), 1, &dwRecvBytes, &dwFlags, &(g_socketsg_dwEventTotal-o), NULL) = SOCKET_ERROR) if (WSAGetLastError() != ERROR_IO_PENDING) printf(错误:WSARecv() failed with error %dn, WSAGetLastError(); return; g_dwEventTotal+; /离开临界区 LeaveCriticalSection(&g_cs); /使第一个事件有信号。使工作者线程处理其他的事件 if (WSASetEvent(g_events0) = FALSE) printf(错误:WSASetEvent failed with error %dn, 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 %dn, WSAGetLastError(); return 0; if (g_index - WSA_WAIT_EVENT_0) = 0) WSAResetEvent(g_events0); continue; pSI = g_socketsg_index - WSA_WAIT_EVENT_0; WSAResetEvent(g_eventsg_index - WSA_WAIT_EVENT_0); if (WSAGetOverlappedResult(pSI-s, &(pSI-o), &dwBytesTransferred, FALSE, &dwFlags) = FALSE | dwBytesTransferred = 0) printf(Closing socket %dn, pSI-s); if (closesocket(pSI-s) = SOCKET_ERROR) printf(错误:closesocket() failed with error %dn, WSAGetLastError(); GlobalFree(pSI); WSACloseEvent(g_eventsg_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 nStatus = WSA_RECV ) memcpy( &pSI-buffRecvpSI-dwBytesRecv,pSI-wsaBuf.buf,dwBytesTransferred); pSI-dwBytesRecv += dwBytesTransferred; printf( 接受:%sn,pSI-buffRecv); if( pSI-buffRecvpSI-dwBytesRecv-2 = r / 要保证最后是rn& pSI-buffRecvpSI-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_eventsg_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 %dn, 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_eventsg_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 %dn, WSAGetLastError(); return -1;return 0;/显示欢迎消息BOOL WelcomeInfo( SOCKET s )char* szWelcomeInfo = 220 欢迎您登录到Mini FtpServer.rn;if( send( s,szWelcomeInfo,strlen(szWelcomeInfo),0 ) = SOCKET_ERROR ) printf(Ftp client error:%dn, WSAGetLastError() );return FALSE;/ 刚进来,还没连接,故设置初始状态为falseg_bLoggedIn = FALSE;return TRUE;/登录函数int LoginIn( LPSOCKET_INF pSocketInfo )const char* szUserOK = 331 User name okay, need password.rn; const char* szLoggedIn = 230 User logged in, proceed.rn;int nRetVal = 0;static char szUserMAX_NAME_LEN, szPwdMAX_PWD_LEN;LPSOCKET_INF pSI = pSocketInfo;/ 取得登录用户名if( strstr(strupr(pSI-buffRecv),USER) ) sprintf(szUser,%s,pSI-buffRecv+strlen(USER)+1);strtok( szUser,rn);/ 响应信息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,rn);/ 判断用户名跟口令正确性if( stricmp( szPwd,FTP_USER) | stricmp(szUser,FTP_PASS) ) sprintf(pSI-buffSend,530 User %s cannot log in.rn,szUser );printf(User %s cannot log inn,szUser );nRetVal = LOGIN_FAILED; else sprintf(pSI-buffSend,%s,szLoggedIn);printf(User %s logged inn,szUser );nRetVal = LOGGED_IN;if( SendRes( pSI ) = -1 ) return -1;return nRetVal;char* ConvertCommaAddress( char* szAddress, WORD wPort )char szPort10;sprintf( szPort,%d,%d,wPort/256,wPort%256 );char szIpAddr20;sprintf( szIpAddr,%s,szAddress );int idx = 0;while( szIpAddridx ) if( szIpAddridx = . )szIpAddridx = ,;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 szIpAddrMAX_ADDR_LEN; memset( szIpAddr,0,sizeof(szIpAddr) );char szPortMAX_ADDR_LEN; memset( szPort,0, sizeof(szPort) );*pdwIpAddr = 0; *pwPort = 0;while( szAddressidx )if( szAddressidx = , )iCount +;szAddressidx =.;if( iCount 4 )szIpAddridx = szAddressidx;elseszPorti+ = szAddressidx;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 fiMAX_FILE_NUM;int nFiles = GetFileList( fi, MAX_FILE_NUM, *.* );char szTemp128;sprintf( buff,%s, );if( bDetails ) for( int i=0; inBuffSize-128 ) break;if(!strcmp(fii.szFileName,.) continue;if(!strcmp(fii.szFileName,.) continue;/ 时间SYSTEMTIME st;FileTimeToSystemTime(&(fii.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( fii.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )strcat(buff,);strcat(buff, );else strcat(buff, );/ 文件大小sprintf( szTemp,% 9d ,fii.nFileSizeLow );strcat( buff,szTemp );/ 文件名strcat( buff,fii.szFileName );strcat( buff,rn); else for( int i=0; inFiles; i+)if( strlen(buff) + strlen( fii.szFileName ) + 2 0 ) if( !ReadFile( hFile,&buffidx,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 bufDATA_BUFSIZE;char lpFileNameMAX_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,&bufidx,nBytesLeft,0 );if( nBytesRecv = SOCKET_ERROR ) printf(Failed to send buffer to socket %dn,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,&bufidx,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 fi1;int nFiles = GetFileList( fi,1,szFileName );if( nFiles != 1 ) return -1;sprintf( szFileNS, %s,szFileName,fi0.nFileSizeLow );nFileSize = fi0.nFileSizeLow;return nFileSize;intDataConn( SOCKET& s, DWORD dwIp, WORD wPort, int nMode ) / 创建一个sockets = socket( AF_INET,SOCK_STREAM,0 );if( s = INVALID_SOCKET ) printf(Failed to get a socket %dn, 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 = d

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论