给出一个C++或Java编写的ftp服务器程序

给出一个C++或Java编写的ftp服务器程序,第1张

给你一个MFC写的:

// FtpClient.h: interface for the CFtpServer class.

//

#if !defined(_FTPCLIENT_H)

#define _FTPCLIENT_H

#include <afxinet.h>

class CFtpClient

{

//构造/析构函数

public:

CFtpClient(const char *pszFtpIp, const char *pszFtpPort, const char *pszFtpUser, const char *pszFtpPassWord)

//功能:构造函数

//参数:pszFtpIp---------Ftp服务器IP地址

// pszFtpPort-------Ftp服务器端口

// pszFtpUser-------Ftp用户名

// pszFtpPassWord---Ftp用户密码

//返回值:无

virtual ~CFtpClient()

//功能:析构函数

//参数:无

//返回值:无

//公有成员函数

public:

BOOL ConnectFtpServer()

//功能:连接FTP服务器

//参数:无

//返回值:TRUE--连接成功,FALSE--连接失败

void DisConnectFtpServer()

//功能:断开与FTP服务器的连接

//参数:无

//返回值:无

BOOL PutFileToFtpServer(const char *pszFilePath)

//功能:上传指定的文件到FTP服务器

//参数:要上传的文件名

//返回值:TRUE--连接成功,FALSE--连接失败

BOOL GetFileFromFtpServer(const char *pszFilePath)

//功能:从FTP服务器下载指定文件

//参数:要下载的文件名

//返回值:TRUE--连接成功,FALSE--连接失败

CString GetUpLoadFilePath()

//功能:得到上传文件名

//参数:无

//返回值:得到的当前路径

//私有成员变量

private:

charm_szFtpIp[20] //Ftp服务器IP地址

UINTm_uFtpPort //Ftp服务器端口

charm_szFtpUser[20] //Ftp用户名

charm_szFtpPassWord[20] //Ftp用户密码

CInternetSession*m_pInetSession //Internet会话对象指针

CFtpConnection*m_pFtpConnection //FTP服务连接对象指针

}

#endif

// FtpClient.cpp: implementation of the CFtpServer class.

//

#include "FtpClient.h"

CFtpClient::CFtpClient(const char *pszFtpIp, const char *pszFtpPort, const char *pszFtpUser,const char *pszFtpPassWord)

{

strcpy(m_szFtpIp, pszFtpIp)

m_uFtpPort = atoi(pszFtpPort)

strcpy(m_szFtpUser, pszFtpUser)

strcpy(m_szFtpPassWord, pszFtpPassWord)

m_pInetSession = NULL

m_pFtpConnection = NULL

}

CFtpClient::~CFtpClient()

{

}

BOOL CFtpClient::ConnectFtpServer()

{

//创建Internet会话

m_pInetSession = new CInternetSession(AfxGetAppName(), 1, PRE_CONFIG_INTERNET_ACCESS)

try

{

//连接Ftp服务器

m_pFtpConnection = m_pInetSession->GetFtpConnection(m_szFtpIp, m_szFtpUser, m_szFtpPassWord, m_uFtpPort)

}

catch(CInternetException *pEx)

{

char szError[1024]

pEx->GetErrorMessage(szError, 1024)

pEx->Delete()

CLog Log

Log.RecordLog("连接Ftp服务器", CString("9999"), CString(szError))

return FALSE

}

return TRUE

}

void CFtpClient::DisConnectFtpServer()

{

if(m_pFtpConnection != NULL)

{

m_pFtpConnection->Close()

delete m_pFtpConnection

m_pFtpConnection = NULL

}

if(m_pInetSession !=NULL)

{

m_pInetSession->Close()

delete m_pInetSession

m_pInetSession = NULL

}

}

BOOL CFtpClient::PutFileToFtpServer(const char *pszFilePath)

{

//1. 判断服务器是否连接

if(m_pFtpConnection == NULL)

{

return FALSE

}

char szLocalFile[200] = {0}

char szRemoteFile[200] = {0}

//2. 本地文件名

sprintf(szLocalFile, "%s", pszFilePath)

//3. 远程文件名

char szDrive[10] = {0}

char szDir[210] = {0}

char szFileName[70] = {0}

char szExt[10] = {0}

_splitpath(pszFilePath, szDrive, szDir, szFileName, szExt)

sprintf(szRemoteFile, "%s\\%s.%s", g_strEnterpriseID, szFileName, szExt)

//4. 文件上传

if(!m_pFtpConnection->PutFile(szLocalFile, szRemoteFile))

{

return FALSE

}

return TRUE

}

BOOL CFtpClient::GetFileFromFtpServer(const char *pszFilePath)

{

//1. 判断服务器是否连接

if(m_pFtpConnection == NULL)

{

return FALSE

}

char szLocalFile[200] = {0}

char szRemoteFile[200] = {0}

//2. 本地文件名

sprintf(szLocalFile,"%s",pszFilePath)

//3. 远程文件名

char szDrive[10] = {0}

char szDir[210] = {0}

char szFileName[70] = {0}

char szExt[10] = {0}

_splitpath(pszFilePath, szDrive, szDir, szFileName, szExt)

sprintf(szRemoteFile, "%s\\%s.%s", g_strEnterpriseID, szFileName, szExt)

//4. 文件下载

if(!m_pFtpConnection->GetFile(szRemoteFile, szLocalFile))

{

return FALSE

}

return TRUE

}

CString CFtpClient::GetUpLoadFilePath()

{

CString strPath = "", strDir = ""

//得到当前日期

CTime time = CTime::GetCurrentTime()

CString strDate = time.Format("%Y%m%d")

//得到上传文件路径

char filepath[MAX_PATH]

GetModuleFileName(NULL, filepath, MAX_PATH)

strDir.Format("%s", filepath)

strPath = strDir.Left(strDir.ReverseFind('\\')) + strDate + "\\*.txt"

return strPath

}

//保存成两个文件,然后添加到你的工程中就可以调用了。

什么是FTP呢?FTP 是 TCP/IP 协议组中的协议之一,是英文File Transfer Protocol的缩写。该协议是Internet文件传送的基础,它由一系列规格说明文档组成,目标是提高文件的共享性,提供非直接使用远程计算机,使存储介质对用户透明和可靠高效地传送数据。简单的说,FTP就是完成两台计算机之间的拷贝,从远程计算机拷贝文件至自己的计算机上,称之为“下载(download)”文件。若将文件从自己计算机中拷贝至远程计算机上,则称之为“上载(upload)”文件。在TCP/IP协议中,FTP标准命令TCP端口号为21,Port方式数据端口为20。FTP协议的任务是从一台计算机将文件传送到另一台计算机,它与这两台计算机所处的位置、联接的方式、甚至是是否使用相同的 *** 作系统无关。假设两台计算机通过ftp协议对话,并且能访问Internet, 你可以用ftp命令来传输文件。每种 *** 作系统使用上有某一些细微差别,但是每种协议基本的命令结构是相同的。

FTP的传输有两种方式:ASCII传输模式和二进制数据传输模式。

1.ASCII传输方式:假定用户正在拷贝的文件包含的简单ASCII码文本,如果在远程机器上运行的不是UNIX,当文件传输时ftp通常会自动地调整文件的内容以便于把文件解释成另外那台计算机存储文本文件的格式。

但是常常有这样的情况,用户正在传输的文件包含的不是文本文件,它们可能是程序,数据库,字处理文件或者压缩文件(尽管字处理文件包含的大部分是文本,其中也包含有指示页尺寸,字库等信息的非打印字符)。在拷贝任何非文本文件之前,用binary 命令告诉ftp逐字拷贝,不要对这些文件进行处理,这也是下面要讲的二进制传输。

2.二进制传输模式:在二进制传输中,保存文件的位序,以便原始和拷贝的是逐位一一对应的。即使目的地机器上包含位序列的文件是没意义的。例如,macintosh以二进制方式传送可执行文件到Windows系统,在对方系统上,此文件不能执行。

如果你在ASCII方式下传输二进制文件,即使不需要也仍会转译。这会使传输稍微变慢 ,也会损坏数据,使文件变得不能用。(在大多数计算机上,ASCII方式一般假设每一字符的第一有效位无意义,因为ASCII字符组合不使用它。如果你传输二进制文件,所有的位都是重要的。)如果你知道这两台机器是同样的,则二进制方式对文本文件和数据文件都是有效的。

5. FTP的工作方式

FTP支持两种模式,一种方式叫做Standard (也就是 PORT方式,主动方式),一种是 Passive (也就是PASV,被动方式)。 Standard模式 FTP的客户端发送 PORT 命令到FTP服务器。Passive模式FTP的客户端发送 PASV命令到 FTP Server。

下面介绍一个这两种方式的工作原理:

Port模式FTP 客户端首先和FTP服务器的TCP 21端口建立连接,通过这个通道发送命令,客户端需要接收数据的时候在这个通道上发送PORT命令。 PORT命令包含了客户端用什么端口接收数据。在传送数据的时候,服务器端通过自己的TCP 20端口连接至客户端的指定端口发送数据。 FTP server必须和客户端建立一个新的连接用来传送数据。

Passive模式在建立控制通道的时候和Standard模式类似,但建立连接后发送的不是Port命令,而是Pasv命令。FTP服务器收到Pasv命令后,随机打开一个高端端口(端口号大于1024)并且通知客户端在这个端口上传送数据的请求,客户端连接FTP服务器此端口,然后FTP服务器将通过这个端口进行数据的传送,这个时候FTP server不再需要建立一个新的和客户端之间的连接。

很多防火墙在设置的时候都是不允许接受外部发起的连接的,所以许多位于防火墙后或内网的FTP服务器不支持PASV模式,因为客户端无法穿过防火墙打开FTP服务器的高端端口;而许多内网的客户端不能用PORT模式登陆FTP服务器,因为从服务器的TCP 20无法和内部网络的客户端建立一个新的连接,造成无法工作。

简单上传下载实例(/*....*/为注释):

先假设有一FTP服务器,FTP服务器:qint.ithot.net,用户名:username 密码:user1234。在本地电脑D:盘创建一个文件夹"qint"。将要上传的文件复制到d:\qint里。通过FTP命令将文件从本地上传,从服务器下载的步骤如下:

1.“开始”-“运行”-输入“FTP”

2.open qint.ithot.net

/*这一步可以与第一步合并,在“运行”里直接输入"ftp qint.ithot.net"。如果你的FTP服务器不是用的21默认端口,假如端口是2121,那么此步的命令应在后面空格加2121,即“open qint.ithot.net 2121”*/

3.username

/*提示你输入用户名*/

4.user1234

/*提示你输入密码,密码不回显,打完密码后回车即可。如果你的密码输入错误,将不会提示你重新输入,这时你要键入“user”命令,将会出现第三步,你可以重新输入用户名和密码。*/

5.dir

/*你成功登陆后就可以用dir查看命令查看FTP服务器中的文件及目录,用ls命令只可以查看文件。*/

6.mkdir qint

/*在FTP服务器上根目录下建立qint目录。*/

7.cd qint

/*进入目录qint,用“cd 你的目录名”可以进入当前目录的下一级目录,这跟DOS一样。*/

8.bin

/*采用二进制传输。如果你要上传下载,这一步很重要,不先执行这个命令,上传下载会很慢。*/

9.lcd d:\qint

/*定位本地默认文件夹,在前面我事先在D:盘创建的。*/

10.!dir

/*查看本地文件夹中的文件及目录*/

11.put i001.jpg

/*将当前目录(d:\qint)中的文件i001.jpg上传到FTP服务器默认目录。可以用"mput *.*"将所有文件上传到FTP服务器上。*/

12.get d123.jpg

/*将FTP服务器默认目录中的文件d123.jpg下载到当前目录下(d:\qint)。可以用"mget *.*"将所有文件下载到d:\qint*/

13.delete *.*

/*删除目录qint中的所有文件。*/

14.cd ..

/*返回至上一级目录,即根目录。返回上一级目录用“cd ..”要注意,中间有空格。返回根目录用“cd \”。*/

15.mrdir qint

/*删除目录qint。删除目录,在此目录下不能有文件及目录,不然将无法删除。*/

16.bye

/*退出FTP服务器*/

上传下载时特别要注意服务器及本地电脑的当前目录,文件是从哪里到哪里的问题。查看FTP服务器的当前目录命令为pwd,可以用cd命令定位服务器的目录。可以用lcd命令定位本地电脑的目录。以上实例应用到了采用FTP命令行方式上传下载的最常用命令,你还可以用命令“?”查看更多的命令。

FTP 命令 FTP 的主要 *** 作都是基于各种命令基础之上的 常用的命令有 · 设置传输模式 它包括ASCⅡ(文本) 和BINARY 二进制模式· 目录 *** 作 改变或显示远程计算机的当前目录(cd dir/ls 命令)· 连接 *** 作 open命令用于建立同远程计算机的连接 close命令用于关闭连接· 发送 *** 作 put命令用于传送文件到远程计算机 mput 命令用于传送多个文件到远程计算机· 获取 *** 作 get命令用于接收一个文件 mget命令用于接收多个文件 编程思路 根据FTP 的工作原理 在主函数中建立一个服务器套接字端口 等待客户端请求 一旦客户端请求被接受 服务器程序就建立一个服务器分线程 处理客户端的命令 如果客户端需要和服务器端进行文件的传输 则建立一个新的套接字连接来完成文件的 *** 作 编程技巧说明 主函数设计在主函数中 完成服务器端口的侦听和服务线程的创建 我们利用一个静态字符串变量initDir 来保存服务器线程运行时所在的工作目录 服务器的初始工作目录是由程序运行时用户输入的 缺省为C盘的根目录 具体的代码如下 public class ftpServer extends Thread{private Socket socketClientprivate int counterprivate static String initDirpublic static void main(String[] args){if(args length != ) {initDir = args[ ]}else{ initDir = c: }int i = try{System out println( ftp server started! )//监听 号端口ServerSocket s = new ServerSocket( )for(){//接受客户端请求Socket ining = s accept()//创建服务线程new ftpServer(ining i) start()i++}}catch(Exception e){}} 线程类的设计线程类的主要设计都是在run()方法中实现 用run()方法得到客户端的套接字信息 根据套接字得到输入流和输出流 向客户端发送欢迎信息 FTP 命令的处理( ) 访问控制命令· user name(user) 和 password (pass) 命令处理代码如下 if(str startsWith( USER )){user = str substring( )user = user trim()out println( Password )}if(str startsWith( PASS ))out println( User +user+ logged in )User 命令和 Password 命令分别用来提交客户端用户输入的用户名和口令 · CWD (CHANGE WORKING DIRECTORY) 命令处理代码如下 if(str startsWith( CWD )){String str = str substring( )dir = dir+ / +str trim()out println( CWD mand succesful )}该命令改变工作目录到用户指定的目录 · CDUP (CHANGE TO PARENT DIRECTORY) 命令处理代码如下 if(str startsWith( CDUP )){int n = dir lastIndexOf( / )dir = dir substring( n)out println( CWD mand succesful )}该命令改变当前目录为上一层目录 · QUIT命令处理代码如下 if(str startsWith( QUIT )) {out println( GOOD BYE )done = true}该命令退出及关闭与服务器的连接 输出GOOD BYE ( ) 传输参数命令· Port命令处理代码如下 if(str startsWith( PORT )) {out println( PORT mand successful )int i = str length() int j = str lastIndexOf( )int k = str lastIndexOf( j )String str str str = str = for(int l=k+ lstr = str + str charAt(l)}for(int l=j+ l<=il++){str = str + str charAt(l)}tempPort = Integer parseInt(str ) * * +Integer parseInt(str )}使用该命令时 客户端必须发送客户端用于接收数据的 位IP 地址和 位 的TCP 端口号 这些信息以 位为一组 使用十进制传输 中间用逗号隔开 · TYPE命令处理代码如下 if(str startsWith( TYPE )){out println( type set )}TYPE 命令用来完成类型设置 ( ) FTP 服务命令· RETR (RETEIEVE) 和 STORE (STORE)命令处理的代码if(str startsWith( RETR )){out println( Binary data connection )str = str substring( )str = str trim()RandomAccessFile outFile = newRandomAccessFile(dir+ / +str r )Socket tempSocket = new Socket(host tempPort)OutputStream outSocket = tempSocket getOutputStream()byte byteBuffer[]= new byte[ ]int amounttry{while((amount = outFile read(byteBuffer)) != ){outSocket write(byteBuffer amount)}outSocket close()out println( transfer plete )outFile close()tempSocket close()}catch(IOException e){}}if(str startsWith( STOR )){out println( Binary data connection )str = str substring( )str = str trim()RandomAccessFile inFile = newRandomAccessFile(dir+ / +str rw )Socket tempSocket = new Socket(host tempPort)InputStream inSocket = tempSocket getInputStream()byte byteBuffer[] = new byte[ ]int amounttry{while((amount =inSocket read(byteBuffer) )!= ){inFile write(byteBuffer amount)}inSocket close()out println( transfer plete )inFile close()tempSocket close()}catch(IOException e){}}文件传输命令包括从服务器中获得文件RETR和向服务器中发送文件STOR 这两个命令的处理非常类似 处理RETR命令时 首先得到用户要获得的文件的名称 根据名称创建一个文件输入流 然后和客户端建立临时套接字连接 并得到一个输出流 随后 将文件输入流中的数据读出并借助于套接字输出流发送到客户端 传输完毕以后 关闭流和临时套接字 STOR 命令的处理也是同样的过程 只是方向正好相反 · DELE (DELETE)命令处理代码如下 if(str startsWith( DELE )){str = str substring( )str = str trim()File file = new File(dir str)boolean del = file delete()out println( delete mand successful )}DELE 命令用于删除服务器上的指定文件 · LIST命令处理代码如下 if(str startsWith( LIST )) {try{out println( ASCII data )Socket tempSocket = new Socket(host tempPort)PrintWriter out = new PrintWriter(tempSocket getOutputStream() true)File file = new File(dir)String[] dirStructure = new String[ ]dirStructure= file list()String strType= for(int i= iif( dirStructure[i] indexOf( ) == ) { strType = d }else{strType = }out println(strType+dirStructure[i])}tempSocket close()out println( transfer plete )}catch(IOException e){}LIST 命令用于向客户端返回服务器中工作目录下的目录结构 包括文件和目录的列表 处理这个命令时 先创建一个临时的套接字向客户端发送目录信息 这个套接字的目的端口号缺省为 然后为当前工作目录创建File 对象 利用该对象的list()方法得到一个包含该目录下所有文件和子目录名称的字符串数组 然后根据名称中是否含有文件名中特有的 来区别目录和文件 最后 将得到的名称数组通过临时套接字发送到客户端 lishixinzhi/Article/program/Java/JSP/201311/19211


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/11311578.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-15
下一篇 2023-05-15

发表评论

登录后才能评论

评论列表(0条)

保存