FTP服务器C++代码实现
准备工作VC6.0添加ws2_32.lib到工程,如下图操作:1.首先添加winsock库到工程
2.添加lib库文件
3.添加ws2_32.lib切记用空格隔开
4.点击OK即可
源代码:
FTP_Client:
#pragma comment( lib, "ws2_32.lib" )
#include
#include
#include
#include
#include
#include
#define TRAN_SUCCESS 1 //传输成功
#define SOCK_WSA_ERR (-1) //启动winsock库失败
#define SOCK_CRSOCK_ERR (-2) //创建套接字失败
#define SOCK_BIND_ERR (-3) //绑定端口失败
#define SOCK_LISTEN_ERR (-4) //监听失败
#define SOCK_ACCEPT_ERR (-5) //等待连接失败
#define SOCK_SEND_ERR (-6) //发送数据失败
#define SOCK_CLOSE_ERR (-7) //关闭SOCKET失败#define SOCK_RECVE_ERR (-8) //接受数据失败
#define SOCK_CONNECT_ERR (-10)
#define FILE_ERR (-9) //文件错误
#define Other_ERR (0) //其他不明原因
#define SVR_PORT 6000 //服务器端口
#define SEND_BUFFER_SIZE 4096 //每次发送大小
#define RECV_BUFFER_SIZE 4096 //每次发送大小
struct Fileinfo
{
char fileName[50]; //文件名
int fileBlock; //文件分块大小
int BlockNum; //文件块数量
unsigned long fileSize; //文件总大小
};
int RecevData( SOCKET s );
int Client(char* fileName);
void PrintReturn(int nRet);
int Client( char* strIP)
//int Client()
//int Client(char* fileName)
{
int nResult = 0;
//1、启动Winsock:对Winsock DLL进行初始化,协商Winsock的版本支持并分配必要的资源。(服务器端和客户端)
WORD wV ersion = MAKEWORD( 2, 0 );//wversion为winsock库的版本,高位字节为副版本,地位字节为主版本
WSADA TA wsData;
nResult = WSAStartup( wV ersion, &wsData );//加载winsock库,wsData参数是指向LPWSADA TA结构的指针
if( nResult !=0 )
{
return SOCK_WSA_ERR;
}
if( LOBYTE( wsData.wV ersion ) != 2 ||
HIBYTE( wsData.wV ersion ) != 0 )
{
WSACleanup();
// return;
exit(0);
}
//2、创建套接字:(服务器端和客户端)
SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );//创建套接字
if( s == INV ALID_SOCKET )
{
return SOCK_CRSOCK_ERR; //错误处理
}
/*
unsigned long uladdr;
uladdr = inet_addr("127.0.0.1");
//sock=socket(AF_INET,SOCK_STREAM,0);
sockaddr_in sa;
memset(&sa,0,sizeof(sa));
sa.sin_family=AF_INET;
sa.sin_port=htons(5150);
sa.sin_addr.S_un.S_addr=uladdr;
nResult = connect(s,(const sockaddr*)&sa,sizeof(sa));
//4、套接字的连结:将两个套接字连结起来准备通信。(客户端)
*/
/*int connect(SOCKET s, const struct sockaddr FAR * name, int namelen )
s为欲连结的已创建的套接字。
name为欲连结的socket地址。
namelen为socket地址的结构的长度。*/
unsigned long uladdr;
uladdr = inet_addr(strIP);
// uladdr = inet_addr("192.168.2.79"); //此处设定的是Server端IP地址
// uladdr = inet_addr("127.0.0.1");
sockaddr_in addr;
memset( &addr , 0x00 , sizeof( addr ));
addr. sin_family = AF_INET;
addr. sin_port = htons(SVR_PORT); //保证字节顺序
// addr. sin_addr.s_addr = htonl( uladdr ); //保证字节顺序**********这种写法很奇怪????*************//
addr.sin_addr.S_un.S_addr = uladdr;
nResult = connect( s, ( sockaddr*)&addr, sizeof( sockaddr ) );
if( nResult<0)
{
return SOCK_CONNECT_ERR; //错误处理
}
/************************/
char RecvBuf[100];
recv(s,RecvBuf,100,0);
printf("%s\n",RecvBuf);
// char SendFileName[100];
// send(s,fileName,strlen(fileName) + 1,0);
/************************/
//6、套接字的数据接收:(客户端)
nResult = RecevData( s );
if(nResult<0)
{
return nResult;//错误处理
}
//7、关闭套接字:释放所占有的资源。(服务器端和客户端)nResult=closesocket(s);
if(nResult<0)
{
return SOCK_CLOSE_ERR; //错误处理
}
return TRAN_SUCCESS;
}
//--------------------------------------------------------------------------------- int RecevData( SOCKET s )
{
FILE* stream;
struct Fileinfo fileinfo;
int nRet = 0;
// unsigned long dataLength, cbBytesRet, cbLeftToReceive;
unsigned long dataLength, cbLeftToReceive;
BYTE* recdData = NULL;
memset( &fileinfo, 0x00, sizeof(fileinfo) );
nRet = recv( s , ( char *)&fileinfo, sizeof(fileinfo), 0 );
if( nRet == SOCKET_ERROR )
{
return SOCK_RECVE_ERR;
}
if( ( stream = fopen( fileinfo.fileName, "wb") ) == NULL)
{
return FILE_ERR;
}
// char *tt;
// nRet = send( s, ( char *)"OK" , sizeof( "OK" ),0 );
dataLength = fileinfo.fileSize;
recdData = new byte[RECV_BUFFER_SIZE];
cbLeftToReceive = dataLength;
int ii=0;
do
{
int iiGet, iiRecd;
iiGet = ( cbLeftToReceive < RECV_BUFFER_SIZE ) ? cbLeftToReceive : RECV_BUFFER_SIZE ;
iiRecd = recv( s, ( char *)recdData, iiGet, 0 );
// test for errors and get out if they occurred
if ( iiRecd == SOCKET_ERROR || iiRecd == 0 )
{
return SOCK_RECVE_ERR;
}
printf("%d\n",ii++);
fwrite( recdData, iiRecd, 1, stream ); // Write it
cbLeftToReceive -= iiRecd;
send(s, (char *)&ii,sizeof(ii),0);
}
while ( cbLeftToReceive > 0 );
return TRAN_SUCCESS;
}
void PrintReturn( int nRet)
{
switch( nRet )
{
case TRAN_SUCCESS: cout< case SOCK_WSA_ERR: cout<<"SOCK_WSA_ERR"< 启动winsock失败 case SOCK_CRSOCK_ERR: c out<<"SOCK_CRSOCK_ERR"< 创建套接字失败 case SOCK_BIND_ERR: cout<<"SOCK_BIND_ERR"< case SOCK_LISTEN_ERR: cout<<"SOCK_LISTEN_ERR"< case SOCK_ACCEPT_ERR: cout<<"SOCK_ACCEPT_ERR"< case SOCK_SEND_ERR: cout<<"SOCK_SEND_ERR"< case SOCK_CLOSE_ERR: cout<<"SOCK_CLOSE_ERR"< case SOCK_RECVE_ERR: cout<<"SOCK_RECVE_ERR"< case SOCK_CONNECT_ERR: cout<<"SOCK_CONNECT_ERR"< case FILE_ERR: cout<<"FILE_ERR"< case Other_ERR: cout<<"Other_ERR"< } } int main() { char ip[] = ""; // char filename[] = ""; cout<<"Please enter the FTPServer's IP Address:"< cin>>ip; // scanf("%s",ip); // cout<<"please enter the file you want on the FTP:"< // cin>>filename; // scanf("%s",filename); system("pause"); int nRet = Client(ip); PrintReturn( nRet ); cout<<"Recv OK!!!"< return 0; } FTP_Server: #pragma comment( lib, "ws2_32.lib" ) #include #include #include #include #include #define TRAN_SUCCESS 1 //传输成功 #define SOCK_WSA_ERR (-1) //启动winsock失败 #define SOCK_CRSOCK_ERR (-2) //创建套接字失败 #define SOCK_BIND_ERR (-3) //绑定端口失败 #define SOCK_LISTEN_ERR (-4) //监听失败 #define SOCK_ACCEPT_ERR (-5) //等待连接失败 #define SOCK_SEND_ERR (-6) //发送数据失败 #define SOCK_CLOSE_ERR (-7) //关闭SOCKET失败 #define SOCK_RECVE_ERR (-8) //接受数据失败 #define FILE_ERR (-9) //文件错误 #define Other_ERR (0) //其他不明原因 #define SVR_PORT 6000 //服务器端口 #define SEND_BUFFER_SIZE 4096 //每次发送大小 struct Fileinfo { char fileName[50]; //文件名 int fileBlock; //文件分块大小 int BlockNum; //文件块数量 unsigned long fileSize; //文件总大小 }; bool GetLocalIP( char caIpAddr[] ); int FileSeReturn( int nRet); int FileSend( SOCKET* s ,char* filename ); void Printize(FILE *stream); long filesize(FILE *stream) ; //---------------------------------------------------------------------------------- int ServerSend( char* FileName ) { int nResult = 0; //1、启动Winsock:对Winsock DLL进行初始化,协商Winsock的版本支持并分配必要的资源。(服务器端和客户端) WORD wV ersion = MAKEWORD( 2, 0 ); WSADA TA wsData; nResult = WSAStartup( wV ersion, &wsData ); if( nResult !=0 ) { return SOCK_WSA_ERR; } if( LOBYTE( wsData.wV ersion ) != 2 || HIBYTE( wsData.wV ersion ) != 0 ) { WSACleanup(); // return; exit(0); } //2、创建套接字:(服务器端和客户端) SOCKET s = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );//创建套接字 if( s == INV ALID_SOCKET ) { return SOCK_CRSOCK_ERR; //错误处理 } //获取本地IP地址 /* char caLocalIp[16]="127.0.0.1"; memset( caLocalIp, 0x00, sizeof( caLocalIp ) ); if( !GetLocalIP( caLocalIp ) ) { return SOCK_BIND_ERR; } */ //3、套接字的绑定:将本地地址绑定到所创建的套接字上。(服务器端和客户端) sockaddr_in sockaddr; sockaddr. sin_family =AF_INET;//告知我们正在使用IP地址家族 sockaddr. sin_port = htons(SVR_PORT); //保证字节顺序 // sockaddr. sin_addr.s_addr = inet_addr(caLocalIp);//inet_addr将一个点式IP地址转换为32位的无符号整数 //sockaddr. sin_addr.s_addr = htonl(INADDR_ANY); sockaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); nResult = bind( s,(SOCKADDR*)&sockaddr, sizeof( SOCKADDR ) );//将套接字和一个特定IP地址绑定,s代表我们希望在上面等待客户机连接的那个套接字,addr为一个普通的缓冲区,在此处实际地填充一个地址缓冲区, if( nResult==SOCKET_ERROR) { return SOCK_BIND_ERR; //错误处理 } //4、套接字的监听:(服务器端) nResult = listen( s , 5 ); //最多5个连接 if( nResult == SOCKET_ERROR ) { return SOCK_LISTEN_ERR; //错误处理 } //5、套接字等待连接::(服务器端) sockaddr_in clientaddr; SOCKET s_c; int len; len = sizeof ( clientaddr ); //memset( cliaddr , 0x00, len); s_c = accept( s, ( SOCKADDR*)&clientaddr, &len); /*************/ char sendBuf[100]; sprintf(sendBuf,"Welcome %s to MyFTPServer",inet_ntoa(clientaddr.sin_addr)); send(s_c,sendBuf,strlen(sendBuf) + 1,0); // char recvBuf[100]; // recv(s_c,recvBuf,100,0); // printf("\nThe Client request File is %s\n",recvBuf); /*************/ printf( "A Client connected OK!!!\n" ); if( s_c < 0) { return SOCK_ACCEPT_ERR; //错误处理 } //6、套接字发送数据:(服务器端和客户端) nResult = FileSend( &s_c, FileName ); if( nResult < 0 ) { return nResult;//错误处理 } //7、关闭套接字:释放所占有的资源。(服务器端和客户端) nResult = closesocket( s ); if( nResult == SOCKET_ERROR ) { return SOCK_CLOSE_ERR; //错误处理 } return TRAN_SUCCESS; } //----------------------------------------------------------------------------------------- //发送文件的程序 int FileSend( SOCKET* s ,char* filename ) { FILE* stream; struct Fileinfo fileinfo; int nResult; if( !( stream = fopen(filename, "rb") ) ) { return FILE_ERR; } //*******************************************组织文件基本信息准备发送**************************************** memset( &fileinfo, 0x00, sizeof(fileinfo) ); memcpy( &fileinfo.fileName, filename, sizeof( fileinfo.fileName ) ); fileinfo.fileBlock = SEND_BUFFER_SIZE; long size = filesize( stream ); if(size <= SEND_BUFFER_SIZE) fileinfo.BlockNum = 1; else fileinfo.BlockNum = size / SEND_BUFFER_SIZE + 1; fileinfo.fileSize = filesize( stream ); unsigned int infolen = sizeof( fileinfo ); do { unsigned int len = sizeof( fileinfo ); nResult = send( *s, (char *)&fileinfo , len , 0 ); printf("Send Fileinfo OK!!!\n"); if ( nResult == SOCKET_ERROR ) { return SOCKET_ERROR; } infolen -= nResult; }while( infolen > 0); //发送文件基本信息 printf( "Now OK,Sended File Data!!!\n" ); //发送文件 BYTE sendData[SEND_BUFFER_SIZE] ; memset( sendData ,0x00 , SEND_BUFFER_SIZE ); //sendData = new BYTE[SEND_BUFFER_SIZE]; //每次发送指定大小文件包int allSendSIZE = filesize( stream ); //要发送文件的整个长度 int NUM = fileinfo.BlockNum - 1; int endNum = size % SEND_BUFFER_SIZE; int ii = 1; int jj=1; do { unsigned long sendThisTime, doneSoFar, buffOffset; buffOffset = 0; while( !feof( stream ) ) { if( ii <= NUM) { memset( sendData ,0x00 , SEND_BUFFER_SIZE ); fread( sendData, SEND_BUFFER_SIZE, 1, stream); } else { memset( sendData ,0x00 , SEND_BUFFER_SIZE ); fread( sendData, endNum, 1, stream); } if( allSendSIZE < SEND_BUFFER_SIZE ) sendThisTime = endNum; else sendThisTime = SEND_BUFFER_SIZE; do { doneSoFar = send( *s, (char *)sendData, sendThisTime , 0 ); // test for errors and get out if they occurred if ( doneSoFar == SOCKET_ERROR ) { return SOCKET_ERROR; } buffOffset += doneSoFar; sendThisTime -= doneSoFar; allSendSIZE -= doneSoFar; } while ( sendThisTime > 0 ); recv( *s, ( char *)&ii, sizeof(ii), 0 ); printf("%d\n",jj++); } } while ( allSendSIZE > 0 ); // delete[] sendData; fclose( stream ); return TRAN_SUCCESS; } // 获得本机IP地址 bool GetLocalIP( char caIpAddr[] ) { char caLocalIp[ 16 ]; char caHostName[ 100 ]; int iRtn; // unsigned long ulAddrInfo; struct hostent s_HostEnt, *pHostEnt; struct in_addr s_IpAddr; WORD wV erReq; WSADA TA wsaData; wV erReq = MAKEWORD( 2, 0 ); iRtn = WSAStartup( wV erReq, &wsaData ); if( iRtn != 0 ) { return false; } if( LOBYTE( wsaData.wV ersion ) != 2 || HIBYTE( wsaData.wV ersion ) != 0 ) { WSACleanup(); return false; } memset( caHostName, 0x00, sizeof(caHostName) ); if( gethostname( caHostName, sizeof(caHostName) ) != 0 ) { WSACleanup(); return false; } pHostEnt = &s_HostEnt; pHostEnt = gethostbyname( caHostName ); if( pHostEnt == NULL ) { WSACleanup(); return false; } memcpy( &s_IpAddr, pHostEnt->h_addr_list[0], sizeof(struct in_addr) ); memset( caLocalIp, 0x00, sizeof(caLocalIp) ); strncpy( caLocalIp, inet_ntoa(s_IpAddr), sizeof( caLocalIp ) - 1 ); strncpy( caIpAddr, caLocalIp, sizeof( caLocalIp ) - 1 ); WSACleanup(); return true; } void PrintReturn( int nRet) { switch( nRet ) { case TRAN_SUCCESS: cout< case SOCK_WSA_ERR: cout<<"SOCK_WSA_ERR"< case SOCK_CRSOCK_ERR: c out<<"SOCK_CRSOCK_ERR"< case SOCK_BIND_ERR: cout<<"SOCK_BIND_ERR"< case SOCK_LISTEN_ERR: cout<<"SOCK_LISTEN_ERR"< case SOCK_ACCEPT_ERR: cout<<"SOCK_ACCEPT_ERR"< case SOCK_SEND_ERR: cout<<"SOCK_SEND_ERR"< case SOCK_CLOSE_ERR: cout<<"SOCK_CLOSE_ERR"< case SOCK_RECVE_ERR: cout<<"SOCK_RECVE_ERR"< //case SOCK_CONNECT_ERR: cout<<"SOCK_CONNECT_ERR"< case FILE_ERR: cout<<"FILE_ERR"< case Other_ERR: cout<<"Other_ERR"< } } long filesize(FILE *stream) { long curpos, length; curpos = ftell(stream); fseek(stream, 0L, SEEK_END); length = ftell(stream); fseek(stream, curpos, SEEK_SET); return length; } int main() { char filename[256]; memset( filename, 0x00, sizeof( filename ) ); //strncpy()可以将一字符串的一部分拷贝到另一字符串中 strncpy( filename, "sprintf.doc", sizeof( filename) ); int nRet = ServerSend( filename); PrintReturn( nRet ); cout<<"Server OK!!!"< return 0; }