FTP服务器C++代码实现

FTP服务器C++代码实现
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;

}

相关主题
相关文档
最新文档