FTP服务器源代码C语言

合集下载

windows下FTP下载文件代码(c语言)

windows下FTP下载文件代码(c语言)

windows下FTP下载⽂件代码(c语⾔)windows下FTP下载⽂件(c语⾔)(⽆注释版)#include <stdio.h>#include <windows.h>#include <wininet.h>#include <process.h>#pragma comment(lib, "WININET.LIB")int main(){BOOL bSuccess;HINTERNET hIntSession;HINTERNET hFtpSession;//HINTERNET hFind;//char szBuffer[64];//WIN32_FIND_DATA findData;char szAppName[] = "mydll";char szServer[] = "192.168.101.225";char szUser[] = "qpid";char szPwd[] = "qpid";char szDirectory[] = "/home/qpid/mydll";char szFile[] = "mylib.dll";char szCurDir[MAX_PATH];char szNewFile[] = "c:\\mylib.dll";DWORD dwCurDir = MAX_PATH;printf("try to open intSession...\n");hIntSession = InternetOpen(szAppName, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);if(hIntSession == NULL){printf("can not open intSession!\n");return -1;}printf("intSession is open!\n");printf("try to open ftpSession...\n");hFtpSession = InternetConnect(hIntSession, szServer, INTERNET_DEFAULT_FTP_PORT, szUser, szPwd, INTERNET_SERVICE_FTP, 0, 0); if(hFtpSession == NULL){InternetCloseHandle(hIntSession);printf("can not open ftpSession!\n");return -1;}printf("ftpSession is open!\n");ZeroMemory(szCurDir, sizeof(szCurDir));FtpGetCurrentDirectory(hFtpSession, szCurDir, &dwCurDir);printf("current dir is %s .\n", szCurDir);printf("try to set current directory...\n");bSuccess = FtpSetCurrentDirectory(hFtpSession, szDirectory);if(!bSuccess){InternetCloseHandle(hFtpSession);InternetCloseHandle(hIntSession);printf("can not set directory!\n");return -1;}printf("set directory ok!\n");printf("set directory ok!\n");printf("try to get file...\n");FtpGetFile(hFtpSession, szFile, szNewFile, TRUE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY, 0);//InternetCloseHandle(hFind);InternetCloseHandle(hFtpSession);InternetCloseHandle(hIntSession);return 0;}。

FTP服务器源代码C语言

FTP服务器源代码C语言

/***********************************************************************
函数名:main
说明: 主函数
输入参数: int argc 输入参数长度 char *argv[]输入参数,用于传入监听端口号
***********************************************************************/
{
printf("quit \n");
sprintf(SendBuffer, "221 Bye bye ... \r\n");
bytes = send(h_NewSocket, SendBuffer,strlen(SendBuffer), 0);
}
}
closesocket(h_NewSocket);
printf("%s disconnected from port %d, control socket is closed.\n", inet_ntoa(RemoteAddr.sin_addr),ntohs(SLocalAddr.sin_port));
iSynError=1;
while (1)
{
bytes = recv(h_NewSocket, &RecvBuffer[n], 1, 0);
break;
printf("The Server received: '%s' cmd from client \n", RecvBuffer);
//命令识别
//查看当前目录

C语言实现FTP客户端上传下载功能 ftpClient.h

C语言实现FTP客户端上传下载功能 ftpClient.h

#ifndef _ftpClient_h#define _ftpClient_h#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <sys/stat.h>#include <errno.h>#include <dirent.h>/* 服务器回应响应码*/#define Establish_Successful "257"#define Establish_Fail "550"/* 客户端上传文件的目录路径*/#define CLIENTUPDIRPATH "../file/upfile/"/* 客户端上传文件夹路径*/#define DIRPATH "../file/"/* 下载文件到哪个目录*/#define CLIENTDOWNDIRPATH "../file/downfile/"#define BUFSIZE 128#define FILESIZE_213 213#define FILESIZE_550 550/*遍历目录下所有的文件保存在数组中*/extern int ftpControlConnect(int fd_control, int serverPort, char *serverIp); extern void ftpClientLogin(int fd,char *UserName, char *Password);extern int ftpServerIntoPassiveMode(int fd);extern int ftpDataConnect(int fd , int fd1, int passModePort, char *serverIp ); extern void ftpDownfilePassiveMode(int fd, int fd1, char *filename);extern void ftpUpfilePassiveMode(int fd, int fd1, char *filename);extern off_t getClientFileSize(char *filePath);extern off_t getServerFileSize(int fd, char *filename);extern void judgeFileIsServerAndUp(int fd ,int fd1, char *filename);extern void UploadDirectory(int fd, int fd1, int passModePort , char *serverIp, char *dirname);extern void showCurrentDir(int fd);extern void changeDirectory(int fd, char *dirname);extern void createDirectory(int fd, char *dirname);extern void deleteDirectory(int fd, char *dirname);extern void touchFile(int fd, char *filename);extern void deleteFile(int fd, char *filename);extern void setDataType(int fd, char *modeOption);extern void listFileInformation(int fd, char *filename);extern void setTransferMode(int fd, char *modeOption);extern void listDirectoryContent(int fd, char *dirname);extern void showContern(int fd);extern void ftpClientQuit(int fd);extern void ftpBreakpointContinuing(int fd, int fd1, int fd2, long offset,char *filename ); #endif。

FTP服务器客户端源代码C语言

FTP服务器客户端源代码C语言
//初始化 winsock
DWORD StartSock() {WSADATA WSAData; if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0) {printf("sock init fail!\n"); return (-1); } return(1); } DWORD CreateSocket() {
closesocket(datatcps); return 0; } //搜索下一个文件 fMoreFiles=FindNextFile(hff,&fd); } closesocket(datatcps); return 1; } int SendFile(SOCKET datatcps,FILE* file) { printf("sending file data.."); for(;;) //从文件中循环读取数据并发送客户端 { int r=fread(sbuff,1,1024,file); if(send(datatcps,sbuff,r,0)==SOCKET_ERROR) { printf("lost the connection to client!\n"); closesocket(datatcps); return 0; } if(r<1024)//文件传送结束 break; } closesocket(datatcps); printf("done\n"); return 1; } //连接
"<<endl
<<" dir...................显示远方当前目录的文件 "<<endl
<<" cd....................改变远方当前目录和路径 "<<endl

FtpClient源代码(C#)

FtpClient源代码(C#)
}
private static int BUFFER_SIZE = 512;
private static Encoding ASCII = Encoding.ASCII;
private bool verboseDebugging = false;
// defaults
private string message = null;
private string result = null;
private int port = 21;
private int bytes = 0;
private int resultCode = 0;
private bool loggedin = false;
}
set
{
this.server = value;
}
}
/// <summary>
/// Gets and Sets the port number.
/// </summary>
/// <returns></returns>
public int RemotePort
using System;
using ;
using System.IO;
using System.Text;
using .Sockets;
using System.Diagnostics;
using System.Runtime.Remoting;
}
}
/// <summary>
/// If the value of mode is true, set binary mode for downloads, else, Ascii mode.

C#程序源代码 FTP程序源代码

C#程序源代码 FTP程序源代码

#region Using directivesusing System;using System.Text;using System.IO;using ;#endregionnamespace Ftp.by.DanielGUO{static class Program{static void Main(string[] args){if (args.Length == 0 || args[0].Equals("/help")){DisplayUsage(); //如果没有输入命令,则输出帮助}else if (args.Length == 1){Console.WriteLine("请等待,正在下载....");Download(args[0]); //如果有一个字串,可以判断为下载命令。

}else if (args.Length == 2){if (args[0].Equals("/list")) // 如果有两个字串,而且第一个字串是/list命令List(args[1]); //那么就输出这个路径下的目录信息elseConsole.WriteLine("请等待,正在上传....");Upload(args[0], args[1]); // 如果有两个字串,而且都不是上述的情况,可以判断为上传}else{Console.WriteLine("不能识别的命令,请参阅帮助: /help"); //如果都不能识别,输出错误信息。

//这里存在一个问题,由于判断命令是通过字串数量来决定,//这种方式不能很好的支持文件夹文件名名称存在空格的情况。

//需要通过空格符号的转义字符%20来实现。

}}static void DisplayUsage() //帮助文件{Console.WriteLine();Console.WriteLine();Console.WriteLine("使用说明:");Console.WriteLine();Console.WriteLine("在cmd中找到程序所在的目录");Console.WriteLine();Console.WriteLine("1.查看帮助:输入Ftp.DanielGUO /help");Console.WriteLine("2.下载文件:输入Ftp.DanielGUO (FTP下载文件的URL) 默认保存在程序所在目录");Console.WriteLine("3.上传文件:输入Ftp.DanielGUO (需要上传的文件名) (FTP上传URL路径)");Console.WriteLine("4.查看ftp目录:输入Ftp.DanielGUO /list (FTP查看目录的URL)");Console.WriteLine();Console.WriteLine("示例:");Console.WriteLine(" 下载文件Ftp.DanielGUO ftp://myserver/download.txt");Console.WriteLine(" 上传文件Ftp.DanielGUO upload.txt ftp://myserver/upload.txt");Console.WriteLine();Console.WriteLine("注意事项:");Console.WriteLine("1.程序支持非匿名登录,使用通用格式:ftp://username:password@server:port");Console.WriteLine("2.当路径或文件名中存在的空格时,请用URL转义字符%20代替");Console.WriteLine(" 如ftp://.../folder A/file B.txt应该输入成ftp://.../folder%20A/file%20B.txt");Console.WriteLine();}static void Download(string downloadUrl){Stream responseStream = null;FileStream fileStream = null;StreamReader reader = null;try{FtpWebRequest downloadRequest =(FtpWebRequest)WebRequest.Create(downloadUrl);FtpWebResponse downloadResponse =(FtpWebResponse)downloadRequest.GetResponse();responseStream = downloadResponse.GetResponseStream();string fileName =Path.GetFileName(downloadRequest.RequestUri.AbsolutePath);if (fileName.Length == 0){reader = new StreamReader(responseStream);Console.WriteLine(reader.ReadToEnd());}else{fileStream = File.Create(fileName);byte[] buffer = new byte[1024];int bytesRead;while (true){bytesRead = responseStream.Read(buffer, 0, buffer.Length);if (bytesRead == 0)break;fileStream.Write(buffer, 0, bytesRead);}}Console.WriteLine("下载完成.");}catch (UriFormatException ex){Console.WriteLine(ex.Message);}catch (WebException ex){Console.WriteLine(ex.Message);}catch (IOException ex){Console.WriteLine(ex.Message);}finally{if (reader != null)reader.Close();else if (responseStream != null)responseStream.Close();if (fileStream != null)fileStream.Close();}}static void Upload(string fileName, string uploadUrl){Stream requestStream = null;FileStream fileStream = null;FtpWebResponse uploadResponse = null;try{FtpWebRequest uploadRequest =(FtpWebRequest)WebRequest.Create(uploadUrl);uploadRequest.Method = WebRequestMethods.Ftp.UploadFile;uploadRequest.Proxy = null;requestStream = uploadRequest.GetRequestStream();fileStream = File.Open(fileName, FileMode.Open);byte[] buffer = new byte[1024];int bytesRead;while (true){bytesRead = fileStream.Read(buffer, 0, buffer.Length);if (bytesRead == 0)break;requestStream.Write(buffer, 0, bytesRead);}requestStream.Close();uploadResponse =(FtpWebResponse)uploadRequest.GetResponse();Console.WriteLine("上传完成.");}catch (UriFormatException ex){Console.WriteLine(ex.Message);}catch (IOException ex){Console.WriteLine(ex.Message);}catch (WebException ex){Console.WriteLine(ex.Message);}finally{if (uploadResponse != null)uploadResponse.Close();if (fileStream != null)fileStream.Close();if (requestStream != null)requestStream.Close();}}private static void List(string listUrl){StreamReader reader = null;try{FtpWebRequest listRequest =(FtpWebRequest)WebRequest.Create(listUrl);listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;FtpWebResponse listResponse =(FtpWebResponse)listRequest.GetResponse();reader = new StreamReader(listResponse.GetResponseStream());Console.WriteLine(reader.ReadToEnd());Console.WriteLine("以上是该FTP站点的内容列表.");}catch (UriFormatException ex){Console.WriteLine(ex.Message);}catch (WebException ex){Console.WriteLine(ex.Message);}finally{if (reader != null)reader.Close();}}}}。

C语言实现FTP客户端上传下载功能 ftpClient.h

C语言实现FTP客户端上传下载功能 ftpClient.h

#ifndef _ftpClient_h#define _ftpClient_h#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <sys/stat.h>#include <errno.h>#include <dirent.h>/* 服务器回应响应码*/#define Establish_Successful "257"#define Establish_Fail "550"/* 客户端上传文件的目录路径*/#define CLIENTUPDIRPATH "../file/upfile/"/* 客户端上传文件夹路径*/#define DIRPATH "../file/"/* 下载文件到哪个目录*/#define CLIENTDOWNDIRPATH "../file/downfile/"#define BUFSIZE 128#define FILESIZE_213 213#define FILESIZE_550 550/*遍历目录下所有的文件保存在数组中*/extern int ftpControlConnect(int fd_control, int serverPort, char *serverIp); extern void ftpClientLogin(int fd,char *UserName, char *Password);extern int ftpServerIntoPassiveMode(int fd);extern int ftpDataConnect(int fd , int fd1, int passModePort, char *serverIp ); extern void ftpDownfilePassiveMode(int fd, int fd1, char *filename);extern void ftpUpfilePassiveMode(int fd, int fd1, char *filename);extern off_t getClientFileSize(char *filePath);extern off_t getServerFileSize(int fd, char *filename);extern void judgeFileIsServerAndUp(int fd ,int fd1, char *filename);extern void UploadDirectory(int fd, int fd1, int passModePort , char *serverIp, char *dirname);extern void showCurrentDir(int fd);extern void changeDirectory(int fd, char *dirname);extern void createDirectory(int fd, char *dirname);extern void deleteDirectory(int fd, char *dirname);extern void touchFile(int fd, char *filename);extern void deleteFile(int fd, char *filename);extern void setDataType(int fd, char *modeOption);extern void listFileInformation(int fd, char *filename);extern void setTransferMode(int fd, char *modeOption);extern void listDirectoryContent(int fd, char *dirname);extern void showContern(int fd);extern void ftpClientQuit(int fd);extern void ftpBreakpointContinuing(int fd, int fd1, int fd2, long offset,char *filename ); #endif。

FTP服务器详解+源代码

FTP服务器详解+源代码

一个简单的FTP效劳器实例目标FTP是网络上共享资源的常用方法,在本章中我们将实现一个简单的FTP效劳器。

本章知识点:●FTP协议●Socket类和TcpListener类●System.Threading 名称空间5.1 实例功能本实例实现一个简单的FTP效劳器,该效劳器是一个控制台程序,编译后的可执行文件为ftpd.exe,在控制台中键入ftpd后就可启动效劳器,假设要改变ftp效劳器的工作目录,可以键入ftpd –r 后接绝对路径。

图5-1 登陆ftp输入用户名和密码后〔为简化起见我们在程序中省去了验证过程,任何人都可以登陆〕,用户的控制台如图5-2所示,在效劳器上,也出现了该用户的登陆情况〔图5-3〕。

- -优质-. .. -可修编.图5-2 成功登陆 图5-3 效劳端接下来用户可以使用各种命令进展各种ftp 操作,比方列出目录下所有文件和文件夹〔ls 〕,下载指定的文件〔get 〕,上载文件〔put 〕等等。

下面是客户端〔图5-4〕和效劳端〔图5-5〕某时刻的运行状态。

图5-4 客户端运行情况图 5-5 效劳端运行情况5.2 编程思路要实现FTP 效劳器,我们必须对FTP 协议有一定的了解,使用符合协议的指令集和网络传输方式,我们将在下一节详细介绍关于FTP 协议的根底知识。

另外,我们还采用了TcpListener 和Socket 编程技术实现数据传输,所以这也是我们需要掌握的容。

最后,为了同时给多个用户提供效劳,FTP 效劳器还必须支持多线程。

FTP 效劳器程序的大框架是这样的:程序运行后,在效劳器的某个端口有一个TcpListener 一直在监听用户的请求,当有用户请求效劳时,效劳器立刻创立一个新的线程处理这个请求,我们称开场了一个新的会话。

在会话中,效劳器通过Socket 接收用户命令,对命令进展分析后采取相应的操作,并将结果返回。

一直到用户退出这个会话,效劳器才销毁这个线程。

效劳器和客户端的会话方式有两种,一是被动方式〔passive 〕,即效劳器在某个特定端口有一个TcpListener 在不断监听用户命令;二是主动方式,这种情况下,效劳器在该客户端有效劳请求时,创立一个套接字和它进展数据传输。

FTP服务器源代码C语言

FTP服务器源代码C语言

FTP服务器端源代码:// Mini FtpServer.cpp : Defines the entry point for the console application. #include "stdafx.h"#include <string.h>#include <ws2tcpip.h>#include <stdlib.h>#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_USER "toldo"#define FTP_PASS "toldo"#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 buffRecv[DATA_BUFSIZE];CHAR buffSend[DATA_BUFSIZE];WSABUF wsaBuf;SOCKET s;WSAOVERLAPPED o;DWORD dwBytesSend;DWORD dwBytesRecv;int nStatus;} SOCKET_INF, *LPSOCKET_INF;typedef struct {TCHAR szFileName[MAX_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_events[WSA_MAXIMUM_WAIT_EVENTS]; LPSOCKET_INF g_sockets[WSA_MAXIMUM_WAIT_EVENTS]; CRITICAL_SECTION g_cs;char g_szLocalAddr[MAX_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 %d\n", 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 %d\n", 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 %d\n", WSAGetLastError());return;}if (listen(sListen, SOMAXCONN)){printf("错误:listen() failed with error %d\n", 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 %d\n", WSAGetLastError());return;}//创建第一个手动重置对象if ((g_events[0] = WSACreateEvent()) == WSA_INVALID_EVENT){printf("错误:WSACreateEvent failed with error %d\n", WSAGetLastError());return;}// 创建一个线程处理请求if (CreateThread(NULL, 0, ProcessTreadIO, NULL, 0, &dwThreadId) == NULL) {printf("错误:CreateThread failed with error %d\n", GetLastError());return;}g_dwEventTotal = 1;while(TRUE){//处理入站连接if ((sAccept = accept(sListen, NULL, NULL)) == INVALID_SOCKET){printf("错误:accept failed with error %d\n", WSAGetLastError());return;}//回传欢迎消息if( !WelcomeInfo( sAccept ) ) break;//设置ftp根目录if( !SetCurrentDirectory( DEFAULT_HOME_DIR ) ) break;//操作临界区,防止出错EnterCriticalSection(&g_cs);//创建一个新的SOCKET_INF结构处理接受的数据socket.if ((g_sockets[g_dwEventTotal] = (LPSOCKET_INF)GlobalAlloc(GPTR,sizeof(SOCKET_INF))) == NULL){printf("错误:GlobalAlloc() failed with error %d\n", GetLastError());return;}//初始化新的SOCKET_INF结构char buff[DATA_BUFSIZE]; memset( buff,0,DATA_BUFSIZE );g_sockets[g_dwEventTotal]->wsaBuf.buf = buff;g_sockets[g_dwEventTotal]->wsaBuf.len = DATA_BUFSIZE;g_sockets[g_dwEventTotal]->s = sAccept;memset(&(g_sockets[g_dwEventTotal]->o),0, sizeof(OVERLAPPED));g_sockets[g_dwEventTotal]->dwBytesSend = 0;g_sockets[g_dwEventTotal]->dwBytesRecv = 0;g_sockets[g_dwEventTotal]->nStatus = WSA_RECV; // 接收//创建事件if ((g_sockets[g_dwEventTotal]->o.hEvent = g_events[g_dwEventTotal] = WSACreateEvent()) == WSA_INVALID_EVENT){printf("WSACreateEvent() failed with error %d\n", WSAGetLastError());return;}//发出接受请求dwFlags = 0;if (WSARecv(g_sockets[g_dwEventTotal]->s,&(g_sockets[g_dwEventTotal]->wsaBuf), 1, &dwRecvBytes, &dwFlags,&(g_sockets[g_dwEventTotal]->o), NULL) == SOCKET_ERROR){if (WSAGetLastError() != ERROR_IO_PENDING){printf("错误:WSARecv() failed with error %d\n", WSAGetLastError());return;}}g_dwEventTotal++;//离开临界区LeaveCriticalSection(&g_cs);//使第一个事件有信号。

C语言小项目:用SOCKET编程实现FTP

C语言小项目:用SOCKET编程实现FTP
7、关闭套接字——closesocket() 功能:关闭套接字 s 格式:BOOL PASCAL FAR closesocket(SOCKET s);
FTP 下载文件流程
FTP 服务端和客户端之间存在两中连接:一中用于传输 FTP 命令(命令必须由客户端主动发起), 连接始终存在;另一中用于向客户端传输数据,每当要传输文件或目录文件列表信息时则建立一个数据连 接,数据传输完毕立即断开。 数据连接有两种建立方式:客户端监听某端口,服务器主动发起数据连接。 服务器监听某端口,客户端主动发起数据连接。下载文件之前首先需要登陆,登陆的状态图如图 2 所示。 如果前面发送的命令均得到成功响应,则表示服务器数据准备完毕。下面需要做的是与服务建立数据连接, 开始接受数据,并将接收到的数据保存在本地文件中,直到接收完毕后断开数据连接,下载完毕。通过访 问全局变量获得 FTP 服务器 IP 地址和端口号,以及登陆的用户名和密码,登陆服务器。 为了实现 FTP 下载文件能成功,我觉得用代码和图片解释比较好,但文字描述不清楚,所以用代码的比较多,虽然觉得 不好,但我只能这样。
SOCKET sListen, sAccept; SOCKADDR_IN inetAddr; DWORD dwFlags; DWORD dwRecvBytes; CServer * server =(CServer*)lpParameter; 2.创建第一个手动重置对象 if ((g_events[0] = WSACreateEvent()) == WSA_INVALID_EVENT) {
三、详细设计
Windows Sockets 实现,一个 Windows Sockets 实现是指实现了 Windows Sockets 规范所描述的全部功 能的一套软件。一般通过 DLL 文件来实现。Windows 环境下进行网络程序设计的最基本方法是应用 Windows Sockets 来实现,通过使用 MFC 提供的 Windows Sockets 类,能够很好的完成 FTP 的功能。

C#上传下载文件ftp操作类FTPClient代码

C#上传下载文件ftp操作类FTPClient代码

C#上传下载文件ftp操作类FTPClient代码C#上传下载文件ftp操作类FTPClient完整代码,可以实现ftp操作功能,如:ftp服务器的登陆,上传和下载一批文件,对目录的添加,删除,修改权限。

public class FTPClient{#region 构造函数/// <summary>/// 缺省构造函数/// </summary>public FTPClient(){strRemoteHost = "";strRemotePath = "/";strRemoteUser = "";strRemotePass = "";strRemotePort = 21;bConnected = false;}/// <summary>/// 构造函数/// </summary>/// <param name="remoteHost"></param>/// <param name="remotePath"></param>/// <param name="remoteUser"></param>/// <param name="remotePass"></param>/// <param name="remotePort"></param>public FTPClient(string remoteHost, string remotePath,string remoteUser, string remotePass, int remotePort ) {strRemoteHost = remoteHost;strRemotePath = remotePath;strRemoteUser = remoteUser;strRemotePass = remotePass;strRemotePort = remotePort;Connect();}#endregion#region 登陆/// <summary>/// FTP服务器IP地址/// </summary>private string strRemoteHost;public string RemoteHost{get{return strRemoteHost;}set{strRemoteHost = value;}}/// <summary>/// FTP服务器端口/// </summary>private int strRemotePort;public int RemotePort{get{return strRemotePort;}set{strRemotePort = value;}}/// <summary>/// 当前服务器目录/// </summary>private string strRemotePath; public string RemotePath {get{return strRemotePath;}set{strRemotePath = value;}}/// <summary>/// 登录用户账号/// </summary>private string strRemoteUser;public string RemoteUser {set{strRemoteUser = value;}}/// <summary>/// 用户登录密码/// </summary>private string strRemotePass; public string RemotePass {set{strRemotePass = value;}}/// <summary>/// 是否登录/// </summary>private Boolean bConnected; public bool Connected{get{return bConnected;}}#endregion#region 链接/// <summary>/// 建立连接/// </summary>public void Connect(){socketControl = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolTy pe.Tcp);IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort);// 链接try{socketControl.Connect(ep);}catch(Exception){throw new IOException("Couldn't connect to remote server");}// 获取应答码ReadReply();if(iReplyCode != 220){DisConnect();throw new IOException(strReply.Substring(4));}// 登陆SendCommand("USER "+strRemoteUser);if( !(iReplyCode == 331 || iReplyCode == 230) ){CloseSocketConnect();//关闭连接throw new IOException(strReply.Substring(4)); }if( iReplyCode != 230 ){SendCommand("PASS "+strRemotePass);if (!(iReplyCode == 230 || iReplyCode == 202)) {CloseSocketConnect();//关闭连接throw new IOException(strReply.Substring(4)); }else{Console.WriteLine("已连接服务器");}}bConnected = true; // 切换到目录ChDir(strRemotePath); //}/// <summary>/// 关闭连接/// </summary>public void DisConnect(){if( socketControl != null ){SendCommand("QUIT");}CloseSocketConnect();}#endregion#region 传输模式/// <summary>/// 传输模式:二进制类型、ASCII类型/// </summary>public enum TransferType {Binary,ASCII}; /// <summary> /// 设置传输模式/// </summary>/// <param name="ttType">传输模式</param>public void SetTransferType(TransferType ttType){if(ttType == TransferType.Binary){SendCommand("TYPE I");//binary类型传输}else{SendCommand("TYPE A");//ASCII类型传输}if (iReplyCode != 200){throw new IOException(strReply.Substring(4));}else{trType = ttType;}}/// <summary>/// 获得传输模式/// </summary>/// <returns>传输模式</returns>public TransferType GetTransferType(){return trType;}#endregion#region 文件操作/// <summary>/// 获得文件列表/// </summary>/// <param name="strMask">文件名的匹配字符串</param> /// <returns></returns>public string[] Dir(string strMask){// 建立链接if(!bConnected){Connect();} //建立进行数据连接的socketSocket socketData = CreateDataSocket();//传送命令SendCommand("NLST " + strMask); //分析应答代码if(!(iReplyCode == 150 || iReplyCode == 125 ||iReplyCode == 226)){throw new IOException(strReply.Substring(4));}//获得结果strMsg = "";while(true){int iBytes = socketData.Receive(buffer,buffer.Length, 0); strMsg += ASCII.GetString(buffer, 0, iBytes);if(iBytes < buffer.Length){break;}}char[] seperator = {'\n'};string[] strsFileList = strMsg.Split(seperator); socketData.Close();//数据socket关闭时也会有返回码if(iReplyCode != 226){ReadReply();if(iReplyCode != 226){throw new IOException(strReply.Substring(4));}}return strsFileList;}/// <summary>/// 获取文件大小/// </summary>/// <param name="strFileName">文件名</param>/// <returns>文件大小</returns>private long GetFileSize(string strFileName){if(!bConnected){Connect();}SendCommand("SIZE " + Path.GetFileName(strFileName)); long lSize=0;if(iReplyCode == 213){lSize = Int64.Parse(strReply.Substring(4));}else{throw new IOException(strReply.Substring(4));}return lSize;}/// <summary>/// 删除/// </summary>/// <param name="strFileName">待删除文件名</param> public void Delete(string strFileName){if(!bConnected){Connect();}SendCommand("DELE "+strFileName);if(iReplyCode != 250){throw new IOException(strReply.Substring(4));}}/// <summary>/// 重命名(如果新文件名与已有文件重名,将覆盖已有文件)/// </summary>/// <param name="strOldFileName">旧文件名</param>/// <param name="strNewFileName">新文件名</param>public void Rename(string strOldFileName,string strNewFileName){if(!bConnected){Connect();}SendCommand("RNFR "+strOldFileName);if(iReplyCode != 350){throw new IOException(strReply.Substring(4));}// 如果新文件名与原有文件重名,将覆盖原有文件SendCommand("RNTO "+strNewFileName);if(iReplyCode != 250){throw new IOException(strReply.Substring(4));}}#endregion#region 上传和下载/// <summary>/// 下载一批文件/// </summary>/// <param name="strFileNameMask">文件名的匹配字符串</param>/// <param name="strFolder">本地目录(不得以\结束)</param>public void Get(string strFileNameMask,string strFolder){if(!bConnected){Connect();}string[] strFiles = Dir(strFileNameMask);foreach(string strFile in strFiles){if(!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串{Get(strFile,strFolder,strFile);}}}/// <summary>/// 下载一个文件/// </summary>/// <param name="strRemoteFileName">要下载的文件名</param>/// <param name="strFolder">本地目录(不得以\结束)</param>/// <param name="strLocalFileName">保存在本地时的文件名</param>public void Get(string strRemoteFileName,stringstrFolder,string strLocalFileName){if(!bConnected){Connect();}SetTransferType(TransferType.Binary);if (strLocalFileName.Equals("")){strLocalFileName = strRemoteFileName;}if(!File.Exists(strLocalFileName)){Stream st = File.Create(strLocalFileName);st.Close();}FileStream output = newFileStream(strFolder + "\\" +strLocalFileName,FileMode.Create);Socket socketData = CreateDataSocket();SendCommand("RETR " + strRemoteFileName);if(!(iReplyCode == 150 || iReplyCode == 125|| iReplyCode == 226 || iReplyCode == 250)){throw new IOException(strReply.Substring(4));}while(true){int iBytes = socketData.Receive(buffer,buffer.Length, 0);output.Write(buffer,0,iBytes);if(iBytes <= 0){break;}}output.Close();if (socketData.Connected){socketData.Close();}if(!(iReplyCode == 226 || iReplyCode == 250)){ReadReply();if(!(iReplyCode == 226 || iReplyCode == 250)){throw new IOException(strReply.Substring(4));}}}/// <summary>/// 上传一批文件/// </summary>/// <param name="strFolder">本地目录(不得以\结束)</param>/// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param>public void Put(string strFolder,string strFileNameMask){string[] strFiles = Directory.GetFiles(strFolder,strFileNameMask);foreach(string strFile in strFiles){//strFile是完整的文件名(包含路径)Put(strFile);}}/// <summary>/// 上传一个文件/// </summary>/// <param name="strFileName">本地文件名</param>public void Put(string strFileName){if(!bConnected){Connect();}Socket socketData = CreateDataSocket();SendCommand("STOR "+Path.GetFileName(strFileName));if( !(iReplyCode == 125 || iReplyCode == 150) ){throw new IOException(strReply.Substring(4));}FileStream input = newFileStream(strFileName,FileMode.Open);int iBytes = 0;while ((iBytes = input.Read(buffer,0,buffer.Length))> 0) {socketData.Send(buffer, iBytes, 0);}input.Close();if (socketData.Connected){socketData.Close();}if(!(iReplyCode == 226 || iReplyCode == 250)){ReadReply();if(!(iReplyCode == 226 || iReplyCode == 250)){throw new IOException(strReply.Substring(4));}}}#endregion#region 目录操作/// <summary>/// 创建目录/// </summary>/// <param name="strDirName">目录名</param> public void MkDir(string strDirName){if(!bConnected){Connect();}SendCommand("MKD "+strDirName);if(iReplyCode != 257){throw new IOException(strReply.Substring(4));}}/// <summary>/// 删除目录/// </summary>/// <param name="strDirName">目录名</param>public void RmDir(string strDirName){if(!bConnected){Connect();}SendCommand("RMD "+strDirName);if(iReplyCode != 250){throw new IOException(strReply.Substring(4));}}/// <summary>/// 改变目录/// </summary>/// <param name="strDirName">新的工作目录名</param>public void ChDir(string strDirName){if(strDirName.Equals(".") || strDirName.Equals("")) {return;}if(!bConnected){Connect();}SendCommand("CWD "+strDirName);if(iReplyCode != 250){throw new IOException(strReply.Substring(4));}this.strRemotePath = strDirName;}#endregion#region 内部变量/// <summary>/// 服务器返回的应答信息(包含应答码)/// </summary>private string strMsg;/// <summary>/// 服务器返回的应答信息(包含应答码)/// </summary>private string strReply;/// <summary>/// 服务器返回的应答码private int iReplyCode;/// <summary>/// 进行控制连接的socket/// </summary>private Socket socketControl;/// <summary>/// 传输模式/// </summary>private TransferType trType;/// <summary>/// 接收和发送数据的缓冲区/// </summary>private static int BLOCK_SIZE = 512;Byte[] buffer = new Byte[BLOCK_SIZE];/// <summary>/// 编码方式/// </summary>Encoding ASCII = Encoding.ASCII;#endregion#region 内部函数/// <summary>/// 将一行应答字符串记录在strReply和strMsg/// 应答码记录在iReplyCode/// </summary>private void ReadReply(){strMsg = "";strReply = ReadLine();iReplyCode = Int32.Parse(strReply.Substring(0,3));/// 建立进行数据连接的socket/// </summary>/// <returns>数据连接socket</returns>private Socket CreateDataSocket(){SendCommand("PASV");if(iReplyCode != 227){throw new IOException(strReply.Substring(4));}int index1 = strReply.IndexOf('(');int index2 = strReply.IndexOf(')');string ipData = strReply.Substring(index1+1,index2-index1-1);int[] parts = new int[6];int len = ipData.Length;int partCount = 0;string buf="";for (int i = 0; i < len && partCount <= 6; i++){char ch = Char.Parse(ipData.Substring(i,1));if (Char.IsDigit(ch)){buf+=ch;}else if (ch != ','){throw new IOException("Malformed PASV strReply: " + strReply);if (ch == ',' || i+1 == len){try{parts[partCount++] = Int32.Parse(buf);buf="";}catch (Exception){throw new IOException("Malformed PASV strReply: " + strReply);}}}string ipAddress = parts[0] + "."+ parts[1]+ "." + parts[2] + "." + parts[3];int port = (parts[4] << 8) + parts[5];Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Stream,Protocol Type.Tcp);IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipAddress), port);try{s.Connect(ep);}catch(Exception){throw new IOException("Can't connect to remote server");return s;}/// <summary>/// 关闭socket连接(用于登录以前)/// </summary>private void CloseSocketConnect(){if(socketControl!=null){socketControl.Close();socketControl = null;}bConnected = false;}/// <summary>/// 读取Socket返回的所有字符串/// </summary>/// <returns>包含应答码的字符串行</returns>private string ReadLine(){while(true){int iBytes = socketControl.Receive(buffer,buffer.Length, 0); strMsg += ASCII.GetString(buffer, 0, iBytes);if(iBytes < buffer.Length){break;}}char[] seperator = {'\n'};string[] mess = strMsg.Split(seperator);if(strMsg.Length > 2){strMsg = mess[mess.Length-2];//seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串,//但也会分配为空字符串给后面(也是最后一个)字符串数组,//所以最后一个mess是没用的空字符串//但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格}else{strMsg = mess[0];}if(!strMsg.Substring(3,1).Equals(" "))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串){return ReadLine();}return strMsg;}/// <summary>/// 发送命令并获取应答码和最后一行应答字符串/// </summary>/// <param name="strCommand">命令</param>private void SendCommand(String strCommand){Byte[] cmdBytes =Encoding.ASCII.GetBytes((strCommand+"\r\n").ToCharArray( ));socketControl.Send(cmdBytes, cmdBytes.Length, 0);ReadReply();}#endregion}以上既为C#上传下载文件ftp操作类FTPClient完整代码,复制既可。

C语言实现FTP服务器

C语言实现FTP服务器

C语⾔实现FTP服务器公共部分代码/*common.h*/#ifndef COMMON_H#define COMMON_H#include <arpa/inet.h>#include <ctype.h>#include <dirent.h>#include <errno.h>#include <fcntl.h>#include <netdb.h>#include <netinet/in.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/wait.h>#include <sys/socket.h>#include <sys/types.h>#include <unistd.h>#define DEBUG 1#define MAXSIZE 512#define CLIENT_PORT_ID 30020struct command{char arg[255];char code[5];};int socket_create(int port);int socket_accept(int sock_listen);int socket_connect(int port, char *host);int recv_data(int sockfd, char* buf, int bufsize);int send_response(int sockfd, int rc);void trimstr(char *str, int n);void read_input(char* buffer, int size);#endif/*common.c*/#include "common.h"/*** 创建监听套接字* 错误返回 -1,正确返回套接字描述符*/int socket_create(int port){int sockfd;int yes = 1;struct sockaddr_in sock_addr;// 创建套接字if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("socket() error");return -1;}// 设置本地套接字地址sock_addr.sin_family = AF_INET;sock_addr.sin_port = htons(port);sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {close(sockfd);perror("setsockopt() error");return -1;}// 绑定本地套接字地址到套接字if (bind(sockfd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) < 0){close(sockfd);perror("bind() error");return -1;}// 将套接字设置为监听状态if (listen(sockfd, 5) < 0){close(sockfd);perror("listen() error");return -1;}return sockfd;}/*** 套接字接受请求* 错误返回 -1,正确返回新的连接套接字*/int socket_accept(int sock_listen){int sockfd;struct sockaddr_in client_addr;socklen_t len = sizeof(client_addr);sockfd = accept(sock_listen, (struct sockaddr *) &client_addr, &len); // 等待连接if (sockfd < 0){perror("accept() error");return -1;}return sockfd;}/*** 连接远端主机* 成功返回套接字描述符,失败返回 -1*/int socket_connect(int port, char*host){int sockfd;struct sockaddr_in dest_addr;/* 创建套接字 */if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("error creating socket");return -1;}/* 设置协议地址 */memset(&dest_addr, 0, sizeof(dest_addr));dest_addr.sin_family = AF_INET;dest_addr.sin_port = htons(port);dest_addr.sin_addr.s_addr = inet_addr(host);/* 在套接字上创建连接 */if(connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0 ){perror("error connecting to server");return -1;}return sockfd;}/*** 接收数据* 错误返回 -1,正确返回接收的字节数*/int recv_data(int sockfd, char* buf, int bufsize){size_t num_bytes;memset(buf, 0, bufsize);/* 调⽤ recv 函数读取套接字数据 */num_bytes = recv(sockfd, buf, bufsize, 0);if (num_bytes < 0)return -1;return num_bytes;}/*** 去除字符串中的空格和换⾏符*/void trimstr(char *str, int n){int i;for (i = 0; i < n; i++){if (isspace(str[i])) str[i] = 0;if (str[i] == '\n') str[i] = 0;}}/*** 发送响应码到 sockfd* 错误返回 -1,正确返回 0*/int send_response(int sockfd, int rc){int conv = htonl(rc);if (send(sockfd, &conv, sizeof conv, 0) < 0 ){perror("error sending...\n");return -1;}return0;}/*** 从命令⾏中读取输⼊*/void read_input(char* buffer, int size){char *nl = NULL;memset(buffer, 0, size);if ( fgets(buffer, size, stdin) != NULL ){nl = strchr(buffer, '\n');if (nl)*nl = '\0'; // 出现换⾏符,则将该位置部位'\0'(字符串结尾)}}客户端代码:/*ftclient.h*/#ifndef FTCLIENT_H#define FTCLIENT_H#include "../common/common.h"int read_reply();void print_reply(int rc);int ftclient_read_command(char* buf, int size, struct command *cstruct); int ftclient_get(int data_sock, int sock_control, char* arg);int ftclient_open_conn(int sock_con);int ftclient_list(int sock_data, int sock_con);int ftclient_send_cmd(struct command *cmd);void ftclient_login();#endifftclient.c*/#include "ftclient.h"int sock_control;/*** 接收服务器响应* 错误返回 -1,正确返回状态码*/int read_reply(){int retcode = 0;if (recv(sock_control, &retcode, sizeof retcode, 0) < 0){perror("client: error reading message from server\n");return -1;}return ntohl(retcode);}/*** 打印响应信息*/void print_reply(int rc){switch (rc){case220:printf("220 Welcome, server ready.\n");break;case221:printf("221 Goodbye!\n");break;case226:printf("226 Closing data connection. Requested file action successful.\n");break;case550:printf("550 Requested action not taken. File unavailable.\n");break;}}/*** 解析命令⾏到结构体*/int ftclient_read_command(char* buf, int size, struct command *cstruct){memset(cstruct->code, 0, sizeof(cstruct->code));memset(cstruct->arg, 0, sizeof(cstruct->arg));printf("ftclient> "); // 输⼊提⽰符fflush(stdout);read_input(buf, size); // 等待⽤户输⼊命令char *arg = NULL;arg = strtok (buf,"");arg = strtok (NULL, "");if (arg != NULL)strncpy(cstruct->arg, arg, strlen(arg));if (strcmp(buf, "list") == 0)strcpy(cstruct->code, "LIST");else if (strcmp(buf, "get") == 0)strcpy(cstruct->code, "RETR");else if (strcmp(buf, "quit") == 0)strcpy(cstruct->code, "QUIT");elsereturn -1; // 不合法memset(buf, 0, 400);strcpy(buf, cstruct->code); // 存储命令到 buf 开始处/* 如果命令带有参数,追加到 buf */if (arg != NULL){strcat(buf, "");strncat(buf, cstruct->arg, strlen(cstruct->arg));}return0;/*** 实现 get <filename> 命令⾏*/int ftclient_get(int data_sock, int sock_control, char* arg){char data[MAXSIZE];int size;FILE* fd = fopen(arg, "w"); // 创建并打开名字为 arg 的⽂件/* 将服务器传来的数据(⽂件内容)写⼊本地建⽴的⽂件 */ while ((size = recv(data_sock, data, MAXSIZE, 0)) > 0)fwrite(data, 1, size, fd);if (size < 0)perror("error\n");fclose(fd);return0;}/*** 打开数据连接*/int ftclient_open_conn(int sock_con){int sock_listen = socket_create(CLIENT_PORT_ID);/* 在控制连接上发起⼀个 ACK 确认 */int ack = 1;if ((send(sock_con, (char*) &ack, sizeof(ack), 0)) < 0){printf("client: ack write error :%d\n", errno);exit(1);}int sock_conn = socket_accept(sock_listen);close(sock_listen);return sock_conn;}/*** 实现 list 命令*/int ftclient_list(int sock_data, int sock_con){size_t num_recvd;char buf[MAXSIZE];int tmp = 0;/* 等待服务器启动的信息 */if (recv(sock_con, &tmp, sizeof tmp, 0) < 0){perror("client: error reading message from server\n");return -1;}memset(buf, 0, sizeof(buf));/* 接收服务器传来的数据 */while ((num_recvd = recv(sock_data, buf, MAXSIZE, 0)) > 0) {printf("%s", buf);memset(buf, 0, sizeof(buf));}if (num_recvd < 0)perror("error");/* 等待服务器完成的消息 */if (recv(sock_con, &tmp, sizeof tmp, 0) < 0){perror("client: error reading message from server\n");return -1;}return0;}/*** 输⼊含有命令(code)和参数(arg)的 command(cmd) 结构* 连接 code + arg,并放进⼀个字符串,然后发送给服务器*/int ftclient_send_cmd(struct command *cmd)char buffer[MAXSIZE];int rc;sprintf(buffer, "%s %s", cmd->code, cmd->arg);/* 发送命令字符串到服务器 */rc = send(sock_control, buffer, (int)strlen(buffer), 0); if (rc < 0){perror("Error sending command to server");return -1;}return0;}/*** 获取登录信息* 发送到服务器认证*/void ftclient_login(){struct command cmd;char user[256];memset(user, 0, 256);/* 获取⽤户名 */printf("Name: ");fflush(stdout);read_input(user, 256);/* 发送⽤户名到服务器 */strcpy(cmd.code, "USER");strcpy(cmd.arg, user);ftclient_send_cmd(&cmd);/* 等待应答码 331 */int wait;recv(sock_control, &wait, sizeof wait, 0);/* 获得密码 */fflush(stdout);char *pass = getpass("Password: ");/* 发送密码到服务器 */strcpy(cmd.code, "PASS");strcpy(cmd.arg, pass);ftclient_send_cmd(&cmd);/* 等待响应 */int retcode = read_reply();switch (retcode){case430:printf("Invalid username/password.\n");exit(0);case230:printf("Successful login.\n");break;default:perror("error reading message from server");exit(1);break;}}/* 主函数⼊⼝ */int main(int argc, char* argv[]){int data_sock, retcode, s;char buffer[MAXSIZE];struct command cmd;struct addrinfo hints, *res, *rp;/* 命令⾏参数合法性检测 */if (argc != 3){printf("usage: ./ftclient hostname port\n");exit(0);}char *host = argv[1]; //所要连接的服务器主机名char *port = argv[2]; //所要链接到服务器程序端⼝号/* 获得和服务器名匹配的地址 */memset(&hints, 0, sizeof(struct addrinfo));hints.ai_family = AF_UNSPEC;hints.ai_socktype = SOCK_STREAM;s = getaddrinfo(host, port, &hints, &res);if (s != 0){printf("getaddrinfo() error %s", gai_strerror(s));exit(1);}/* 找到对应的服务器地址并连接 */for (rp = res; rp != NULL; rp = rp->ai_next){sock_control = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); // 创建控制套接字if (sock_control < 0)continue;if(connect(sock_control, res->ai_addr, res->ai_addrlen)==0) // 和服务器连接break;else{perror("connecting stream socket");exit(1);}close(sock_control);}freeaddrinfo(rp);/* 连接成功,打印信息 */printf("Connected to %s.\n", host);print_reply(read_reply());/* 获取⽤户的名字和密码 */ftclient_login();while (1){ // 循环,直到⽤户输⼊ quit/* 得到⽤户输⼊的命令 */if ( ftclient_read_command(buffer, sizeof buffer, &cmd) < 0){printf("Invalid command\n");continue; // 跳过本次循环,处理下⼀个命令}/* 发送命令到服务器 */if (send(sock_control, buffer, (int)strlen(buffer), 0) < 0 ){close(sock_control);exit(1);}retcode = read_reply(); //读取服务器响应(服务器是否可以⽀持该命令?)if (retcode == 221) // 退出命令{print_reply(221);break;}if (retcode == 502)printf("%d Invalid command.\n", retcode);// 不合法的输⼊,显⽰错误信息else{// 命令合法 (RC = 200),处理命令/* 打开数据连接 */if ((data_sock = ftclient_open_conn(sock_control)) < 0){perror("Error opening socket for data connection");exit(1);}/* 执⾏命令 */if (strcmp(cmd.code, "LIST") == 0)ftclient_list(data_sock, sock_control);else if (strcmp(cmd.code, "RETR") == 0){if (read_reply() == 550) // 等待回复{print_reply(550);close(data_sock);continue;}ftclient_get(data_sock, sock_control, cmd.arg);print_reply(read_reply());}close(data_sock);}} // 循环得到更多的⽤户输⼊close(sock_control); // 关闭套接字控制连接return0;}makefile⽂件CC := gccCFLAGS := -Wall -g -OsSHDIR := ../commonOBJS = ftclient.o $(SHDIR)/common.oall: ftclientftclient: $(OBJS)@$(CC) -o ftclient $(CFLAGS) $(OBJS)$(OBJS) : %.o: %.c@$(CC) -c $(CFLAGS) $< -o $@.PHONY:clean:@rm -f *.o ftclient@rm -f ../common/*.o@echo Done cleaning服务端代码:/*ftserve.h*/#ifndef FTSERVE_H#define FTSERVE_H#include "../common/common.h"void ftserve_retr(int sock_control, int sock_data, char* filename); int ftserve_list(int sock_data, int sock_control);int ftserve_start_data_conn(int sock_control);int ftserve_check_user(char*user, char*pass);int ftserve_login(int sock_control);int ftserve_recv_cmd(int sock_control, char*cmd, char*arg); void ftserve_process(int sock_control);#endif/*ftserve.c*/#include "ftserve.h"/* 主函数⼊⼝ */int main(int argc, char *argv[])int sock_listen, sock_control, port, pid;/* 命令⾏合法性检测 */if (argc != 2){printf("usage: ./ftserve port\n");exit(0);}/* 将命令⾏传进来的服务器端⼝号(字符串)转换为整数 */port = atoi(argv[1]);/* 创建监听套接字 */if ((sock_listen = socket_create(port)) < 0 ){perror("Error creating socket");exit(1);}/* 循环接受不同的客户机请求 */while(1){/* 监听套接字接受连接请求,得到控制套接字,⽤于传递控制信息 */if ((sock_control = socket_accept(sock_listen)) < 0 )break;/* 创建⼦进程处理⽤户请求 */if ((pid = fork()) < 0)perror("Error forking child process");/* ⼦进程调⽤ ftserve_process 函数与客户端交互 */else if (pid == 0){close(sock_listen); // ⼦进程关闭⽗进程的监听套接字ftserve_process(sock_control);close(sock_control); //⽤户请求处理完毕,关闭该套接字exit(0);}close(sock_control); // ⽗进程关闭⼦进程的控制套接字}close(sock_listen);return0;}/*** 通过数据套接字发送特定的⽂件* 控制信息交互通过控制套接字* 处理⽆效的或者不存在的⽂件名*/void ftserve_retr(int sock_control, int sock_data, char* filename){FILE* fd = NULL;char data[MAXSIZE];size_t num_read;fd = fopen(filename, "r"); // 打开⽂件if (!fd)send_response(sock_control, 550); // 发送错误码 (550 Requested action not taken)else{send_response(sock_control, 150); // 发送 okay (150 File status okay)do{num_read = fread(data, 1, MAXSIZE, fd); // 读⽂件内容if (num_read < 0)printf("error in fread()\n");if (send(sock_data, data, num_read, 0) < 0) // 发送数据(⽂件内容)perror("error sending file\n");}while (num_read > 0);send_response(sock_control, 226); // 发送消息:226: closing conn, file transfer successful fclose(fd);}}* 响应请求:发送当前所在⽬录的⽬录项列表* 关闭数据连接* 错误返回 -1,正确返回 0*/int ftserve_list(int sock_data, int sock_control){char data[MAXSIZE];size_t num_read;FILE* fd;int rs = system("ls -l | tail -n+2 > tmp.txt"); //利⽤系统调⽤函数 system 执⾏命令,并重定向到 tmp.txt ⽂件if ( rs < 0){exit(1);}fd = fopen("tmp.txt", "r");if (!fd)exit(1);/* 定位到⽂件的开始处 */fseek(fd, SEEK_SET, 0);send_response(sock_control, 1);memset(data, 0, MAXSIZE);/* 通过数据连接,发送tmp.txt ⽂件的内容 */while ((num_read = fread(data, 1, MAXSIZE, fd)) > 0){if (send(sock_data, data, num_read, 0) < 0)perror("err");memset(data, 0, MAXSIZE);}fclose(fd);send_response(sock_control, 226); // 发送应答码 226(关闭数据连接,请求的⽂件操作成功)return0;}/*** 创建到客户机的⼀条数据连接* 成功返回数据连接的套接字* 失败返回 -1*/int ftserve_start_data_conn(int sock_control){char buf[1024];int wait, sock_data;if (recv(sock_control, &wait, sizeof wait, 0) < 0 ){perror("Error while waiting");return -1;}struct sockaddr_in client_addr;socklen_t len = sizeof client_addr;getpeername(sock_control, (struct sockaddr*)&client_addr, &len); // 获得与控制套接字关联的外部地址(客户端地址) inet_ntop(AF_INET, &client_addr.sin_addr, buf, sizeof(buf));/* 创建到客户机的数据连接 */if ((sock_data = socket_connect(CLIENT_PORT_ID, buf)) < 0)return -1;return sock_data;}/*** ⽤户资格认证* 认证成功返回 1,否则返回 0*/int ftserve_check_user(char*user, char*pass){char username[MAXSIZE];char password[MAXSIZE];char *pch;char buf[MAXSIZE];char *line = NULL;size_t num_read;size_t len = 0;FILE* fd;int auth = 0;fd = fopen(".auth", "r"); //打开认证⽂件(记录⽤户名和密码)if (fd == NULL){perror("file not found");exit(1);}/* 读取".auth" ⽂件中的⽤户名和密码,验证⽤户⾝份的合法性 */ while ((num_read = getline(&line, &len, fd)) != -1){memset(buf, 0, MAXSIZE);strcpy(buf, line);pch = strtok (buf,"");strcpy(username, pch);if (pch != NULL){pch = strtok (NULL, "");strcpy(password, pch);}/* 去除字符串中的空格和换⾏符 */trimstr(password, (int)strlen(password));if ((strcmp(user,username)==0) && (strcmp(pass,password)==0)) {auth = 1; // 匹配成功,标志变量 auth = 1,并返回break;}}free(line);fclose(fd);return auth;}/* ⽤户登录*/int ftserve_login(int sock_control){char buf[MAXSIZE];char user[MAXSIZE];char pass[MAXSIZE];memset(user, 0, MAXSIZE);memset(pass, 0, MAXSIZE);memset(buf, 0, MAXSIZE);/* 获得客户端传来的⽤户名 */if ( (recv_data(sock_control, buf, sizeof(buf)) ) == -1){perror("recv error\n");exit(1);}int i = 5;int n = 0;while (buf[i] != 0) //buf[0-4]="USER"user[n++] = buf[i++];/* ⽤户名正确,通知⽤户输⼊密码 */send_response(sock_control, 331);/* 获得客户端传来的密码 */memset(buf, 0, MAXSIZE);if ( (recv_data(sock_control, buf, sizeof(buf)) ) == -1){perror("recv error\n");exit(1);}i = 5;n = 0;while (buf[i] != 0) // buf[0 - 4] = "PASS"pass[n++] = buf[i++];return (ftserve_check_user(user, pass)); // ⽤户名和密码验证,并返回}/* 接收客户端的命令并响应,返回响应码 */int ftserve_recv_cmd(int sock_control, char*cmd, char*arg){int rc = 200;char buffer[MAXSIZE];memset(buffer, 0, MAXSIZE);memset(cmd, 0, 5);memset(arg, 0, MAXSIZE);/* 接受客户端的命令 */if ((recv_data(sock_control, buffer, sizeof(buffer)) ) == -1){perror("recv error\n");return -1;}/* 解析出⽤户的命令和参数 */strncpy(cmd, buffer, 4);char *tmp = buffer + 5;strcpy(arg, tmp);if (strcmp(cmd, "QUIT")==0)rc = 221;else if ((strcmp(cmd, "USER") == 0) || (strcmp(cmd, "PASS") == 0) || (strcmp(cmd, "LIST") == 0) || (strcmp(cmd, "RETR") == 0))rc = 200;elserc = 502; // ⽆效的命令send_response(sock_control, rc);return rc;}/* 处理客户端请求 */void ftserve_process(int sock_control){int sock_data;char cmd[5];char arg[MAXSIZE];send_response(sock_control, 220); // 发送欢迎应答码/* ⽤户认证 */if (ftserve_login(sock_control) == 1) // 认证成功send_response(sock_control, 230);else{send_response(sock_control, 430); // 认证失败exit(0);}/* 处理⽤户的请求 */while (1){/* 接收命令,并解析,获得命令和参数 */int rc = ftserve_recv_cmd(sock_control, cmd, arg);if ((rc < 0) || (rc == 221)) // ⽤户输⼊命令 "QUIT"break;if (rc == 200 ){/* 创建和客户端的数据连接 */if ((sock_data = ftserve_start_data_conn(sock_control)) < 0){close(sock_control);exit(1);}/* 执⾏指令 */if (strcmp(cmd, "LIST")==0)ftserve_list(sock_data, sock_control);else if (strcmp(cmd, "RETR")==0)ftserve_retr(sock_control, sock_data, arg);close(sock_data);// 关闭连接}}}⾥⾯还有⼀个保存密码账户⽂件.auth,这⾥就不列出。

C#的FTP服务器源代码

C#的FTP服务器源代码

C#的FTP服务器源代码using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;//**new namespaceusing ;using .Sockets;using System.IO;using System.Resources;using System.Text.RegularExpressions;using System.Collections;namespace crFTP{/// <summary>/// FTP类/// </summary>public class FTP{#region 变量声明/// <summary>/// 服务器连接地址/// </summary>public string server;/// <summary>/// 登陆帐号/// </summary>public string user;/// <summary>/// 登陆⼝令/// </summary>public string pass;/// <summary>/// 端⼝号/// </summary>public int port;/// ⽆响应时间(FTP在指定时间内⽆响应) /// </summary>public int timeout;/// <summary>/// 服务器错误状态信息/// </summary>public string errormessage;/// <summary>/// 服务器状态返回信息/// </summary>private string messages;/// <summary>/// 服务器的响应信息/// </summary>private string responseStr;/// <summary>/// 链接模式(主动或被动,默认为被动) /// </summary>private bool passive_mode;/// <summary>/// 上传或下载信息字节数/// </summary>private long bytes_total;/// <summary>/// 上传或下载的⽂件⼤⼩/// </summary>private long file_size;/// <summary>/// 主套接字/// </summary>private Socket main_sock;/// <summary>/// 要链接的⽹络地址终结点/// </summary>private IPEndPoint main_ipEndPoint;/// <summary>/// 侦听套接字/// </summary>private Socket listening_sock;/// <summary>/// </summary>private Socket data_sock;/// <summary>/// 要链接的⽹络数据地址终结点/// </summary>private IPEndPoint data_ipEndPoint;/// <summary>/// ⽤于上传或下载的⽂件流对象/// </summary>private FileStream file;/// <summary>/// 与FTP服务器交互的状态值/// </summary>private int response;/// <summary>/// 读取并保存当前命令执⾏后从FTP服务器端返回的数据信息 /// </summary>private string bucket;#endregion#region 构造函数/// <summary>/// 构造函数/// </summary>public FTP(){server = null;user = null;pass = null;port = 21;passive_mode = true;main_sock = null;main_ipEndPoint = null;listening_sock = null;data_sock = null;data_ipEndPoint = null;file = null;bucket = "";bytes_total = 0;timeout = 10000; //⽆响应时间为10秒messages = "";errormessage = "";}/// <summary>/// 构造函数/// </summary>/// <param name="server">服务器IP或名称</param>/// <param name="user">登陆帐号</param>/// <param name="pass">登陆⼝令</param>public FTP(string server, string user, string pass){this.server = server;er = user;this.pass = pass;port = 21;passive_mode = true;main_sock = null;main_ipEndPoint = null;listening_sock = null;data_sock = null;data_ipEndPoint = null;file = null;bucket = "";bytes_total = 0;timeout = 10000; //⽆响应时间为10秒messages = "";errormessage = "";}/// <summary>/// 构造函数/// </summary>/// <param name="server">服务器IP或名称</param>/// <param name="port">端⼝号</param>/// <param name="user">登陆帐号</param>/// <param name="pass">登陆⼝令</param>public FTP(string server, int port, string user, string pass) {this.server = server;er = user;this.pass = pass;this.port = port;passive_mode = true;main_sock = null;main_ipEndPoint = null;listening_sock = null;data_sock = null;data_ipEndPoint = null;file = null;bucket = "";bytes_total = 0;timeout = 10000; //⽆响应时间为10秒messages = "";errormessage = "";}/// <summary>/// 构造函数/// </summary>/// <param name="server">服务器IP或名称</param>/// <param name="port">端⼝号</param>/// <param name="user">登陆帐号</param>/// <param name="pass">登陆⼝令</param>/// <param name="mode">链接⽅式</param>public FTP(string server, int port, string user, string pass, int mode) {this.server = server;er = user;this.pass = pass;this.port = port;passive_mode = mode <= 1 ? true : false;main_sock = null;main_ipEndPoint = null;listening_sock = null;data_sock = null;data_ipEndPoint = null;file = null;bucket = "";bytes_total = 0;this.timeout = 10000; //⽆响应时间为10秒messages = "";errormessage = "";}/// <summary>/// 构造函数/// </summary>/// <param name="server">服务器IP或名称</param>/// <param name="port">端⼝号</param>/// <param name="user">登陆帐号</param>/// <param name="pass">登陆⼝令</param>/// <param name="mode">链接⽅式</param>/// <param name="timeout">⽆响应时间(限时),单位:秒 (⼩于或等于0为不受时间限制)</param> public FTP(string server, int port, string user, string pass, int mode, int timeout_sec){this.server = server;er = user;this.pass = pass;this.port = port;passive_mode = mode <= 1 ? true : false;main_sock = null;main_ipEndPoint = null;listening_sock = null;data_sock = null;data_ipEndPoint = null;file = null;bucket = "";bytes_total = 0;this.timeout = (timeout_sec <= 0) ? int.MaxValue : (timeout_sec * 1000); //⽆响应时间 messages = "";errormessage = "";}#endregion#region 属性/// <summary>/// 当前是否已连接/// </summary>public bool IsConnected{get{if (main_sock != null)return main_sock.Connected;return false;}}/// <summary>/// 当message缓冲区有数据则返回/// </summary>public bool MessagesAvailable{get{if (messages.Length > 0)return true;return false;}}/// <summary>/// 获取服务器状态返回信息, 并清空messages变量 /// </summary>public string Messages{get{string tmp = messages;messages = "";return tmp;}}/// <summary>/// 最新指令发出后服务器的响应/// </summary>public string ResponseString{get{return responseStr;}}/// <summary>///在⼀次传输中,发送或接收的字节数/// </summary>public long BytesTotal{get{return bytes_total;}}/// <summary>///被下载或上传的⽂件⼤⼩,当⽂件⼤⼩⽆效时为0/// </summary>public long FileSize{get{return file_size;}}/// <summary>/// 链接模式:/// true 被动模式 [默认]/// false: 主动模式/// </summary>public bool PassiveMode{get{return passive_mode;}set{passive_mode = value;}}#endregion#region 操作/// <summary>/// 操作失败/// </summary>private void Fail(){Disconnect();errormessage += responseStr;//throw new Exception(responseStr);}/// <summary>/// 下载⽂件类型/// </summary>/// <param name="mode">true:⼆进制⽂件 false:字符⽂件</param> private void SetBinaryMode(bool mode){if (mode)SendCommand("TYPE I");elseSendCommand("TYPE A");ReadResponse();if (response != 200)Fail();}/// <summary>/// 发送命令/// </summary>/// <param name="command"></param>private void SendCommand(string command){Byte[] cmd = Encoding.ASCII.GetBytes((command + "\r\n").ToCharArray()); if (command.Length > 3 && command.Substring(0, 4) == "PASS"){messages = "\rPASS xxx";}else{messages = "\r" + command;}try{main_sock.Send(cmd, cmd.Length, 0);}catch (Exception ex){try{Disconnect();errormessage += ex.Message;return;}catch{main_sock.Close();file.Close();main_sock = null;main_ipEndPoint = null;file = null;}}}private void FillBucket(){Byte[] bytes = new Byte[512];long bytesgot;int msecs_passed = 0;while (main_sock.Available < 1){System.Threading.Thread.Sleep(50);msecs_passed += 50;//当等待时间到,则断开链接if (msecs_passed > timeout){Disconnect();errormessage += "Timed out waiting on server to respond."; return;}}while (main_sock.Available > 0){bytesgot = main_sock.Receive(bytes, 512, 0);bucket += Encoding.ASCII.GetString(bytes, 0, (int)bytesgot); System.Threading.Thread.Sleep(50);}}private string GetLineFromBucket(){int i;string buf = "";if ((i = bucket.IndexOf('\n')) < 0){while (i < 0){FillBucket();i = bucket.IndexOf('\n');}}buf = bucket.Substring(0, i);bucket = bucket.Substring(i + 1);return buf;}/// <summary>/// 返回服务器端返回信息/// </summary>private void ReadResponse(){string buf;messages = "";while (true){buf = GetLineFromBucket();if (Regex.Match(buf, "^[0-9]+ ").Success){responseStr = buf;response = int.Parse(buf.Substring(0, 3));break;}elsemessages += Regex.Replace(buf, "^[0-9]+-", "") + "\n"; }}/// <summary>/// 打开数据套接字/// </summary>private void OpenDataSocket(){if (passive_mode){string[] pasv;string server;int port;Connect();SendCommand("PASV");ReadResponse();if (response != 227)Fail();int i1, i2;i1 = responseStr.IndexOf('(') + 1;i2 = responseStr.IndexOf(')') - i1;pasv = responseStr.Substring(i1, i2).Split(',');}catch (Exception){Disconnect();errormessage += "Malformed PASV response: " + responseStr;return;}if (pasv.Length < 6){Disconnect();errormessage += "Malformed PASV response: " + responseStr;return;}server = String.Format("{0}.{1}.{2}.{3}", pasv[0], pasv[1], pasv[2], pasv[3]);port = (int.Parse(pasv[4]) << 8) + int.Parse(pasv[5]);try{CloseDataSocket();data_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//#if NET1data_ipEndPoint = new IPEndPoint(Dns.GetHostByName(server).AddressList[0], port);//#else// data_ipEndPoint = new IPEndPoint(.Dns.GetHostEntry(server).AddressList[0], port); //#endifdata_sock.Connect(data_ipEndPoint);}catch (Exception ex){errormessage += "Failed to connect for data transfer: " + ex.Message;return;}}else{Connect();trylistening_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 对于端⼝,则发送IP地址.下⾯则提取相应信息string sLocAddr = main_sock.LocalEndPoint.ToString();int ix = sLocAddr.IndexOf(':');if (ix < 0){errormessage += "Failed to parse the local address: " + sLocAddr;return;}string sIPAddr = sLocAddr.Substring(0, ix);// 系统⾃动绑定⼀个端⼝号(设置 port = 0).IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(sIPAddr), 0);listening_sock.Bind(localEP);sLocAddr = listening_sock.LocalEndPoint.ToString();ix = sLocAddr.IndexOf(':');if (ix < 0){errormessage += "Failed to parse the local address: " + sLocAddr;}int nPort = int.Parse(sLocAddr.Substring(ix + 1));// 开始侦听链接请求listening_sock.Listen(1);string sPortCmd = string.Format("PORT {0},{1},{2}",sIPAddr.Replace('.', ','),nPort / 256, nPort % 256);SendCommand(sPortCmd);ReadResponse();if (response != 200)Fail();}catch (Exception ex){errormessage += "Failed to connect for data transfer: " + ex.Message;return;}}}private void ConnectDataSocket(){try{data_sock = listening_sock.Accept(); // Accept is blockinglistening_sock.Close();listening_sock = null;if (data_sock == null){throw new Exception("Winsock error: " +Convert.ToString(System.Runtime.InteropServices.Marshal.GetLastWin32Error())); }}catch (Exception ex){errormessage += "Failed to connect for data transfer: " + ex.Message;}}private void CloseDataSocket(){if (data_sock != null){if (data_sock.Connected){data_sock.Close();}data_sock = null;}data_ipEndPoint = null;}/// <summary>/// 关闭所有链接/// </summary>public void Disconnect(){CloseDataSocket();if (main_sock != null){if (main_sock.Connected){SendCommand("QUIT");main_sock = null;}if (file != null)file.Close();main_ipEndPoint = null;file = null;}/// <summary>/// 链接到FTP服务器/// </summary>/// <param name="server">要链接的IP地址或主机名</param>/// <param name="port">端⼝号</param>/// <param name="user">登陆帐号</param>/// <param name="pass">登陆⼝令</param>public void Connect(string server, int port, string user, string pass) {this.server = server;er = user;this.pass = pass;this.port = port;Connect();}/// <summary>/// 链接到FTP服务器/// </summary>/// <param name="server">要链接的IP地址或主机名</param>/// <param name="user">登陆帐号</param>/// <param name="pass">登陆⼝令</param>public void Connect(string server, string user, string pass){this.server = server;er = user;this.pass = pass;Connect();}/// <summary>/// 链接到FTP服务器/// </summary>public bool Connect(){errormessage += "No server has been set.\r\n";}if (user == null){errormessage += "No server has been set.\r\n";}if (main_sock != null)if (main_sock.Connected)return true;try{main_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//#if NET1main_ipEndPoint = new IPEndPoint(Dns.GetHostByName(server).AddressList[0], port);//#else// main_ipEndPoint = new IPEndPoint(.Dns.GetHostEntry(server).AddressList[0], port); //#endifmain_sock.Connect(main_ipEndPoint);}catch (Exception ex){errormessage += ex.Message;return false;}ReadResponse();if (response != 220)Fail();SendCommand("USER " + user);ReadResponse();switch (response){case 331:if (pass == null){Disconnect();errormessage += "No password has been set.";return false;}SendCommand("PASS " + pass);ReadResponse();Fail();return false;}break;case 230:break;}return true;}/// <summary>/// 获取FTP当前(⼯作)⽬录下的⽂件列表/// </summary>/// <returns>返回⽂件列表数组</returns> public ArrayList List(){Byte[] bytes = new Byte[512];string file_list = "";long bytesgot = 0;int msecs_passed = 0;ArrayList list = new ArrayList();Connect();OpenDataSocket();SendCommand("LIST");ReadResponse();switch (response){case 125:case 150:break;default:CloseDataSocket();throw new Exception(responseStr); }ConnectDataSocket();while (data_sock.Available < 1){System.Threading.Thread.Sleep(50); msecs_passed += 50;if (msecs_passed > (timeout / 10)) {}while (data_sock.Available > 0){bytesgot = data_sock.Receive(bytes, bytes.Length, 0);file_list += Encoding.ASCII.GetString(bytes, 0, (int)bytesgot); System.Threading.Thread.Sleep(50);}CloseDataSocket();ReadResponse();if (response != 226)throw new Exception(responseStr);foreach (string f in file_list.Split('\n')){if (f.Length > 0 && !Regex.Match(f, "^total").Success)list.Add(f.Substring(0, f.Length - 1));}return list;}/// <summary>/// 获取到⽂件名列表/// </summary>/// <returns>返回⽂件名列表</returns>public ArrayList ListFiles(){ArrayList list = new ArrayList();foreach (string f in List()){if ((f.Length > 0)){if ((f[0] != 'd') && (f.ToUpper().IndexOf("<DIR>") < 0))list.Add(f);}}return list;}/// <summary>/// 获取路径列表/// </summary>/// <returns>返回路径列表</returns>public ArrayList ListDirectories()foreach (string f in List()){if (f.Length > 0){if ((f[0] == 'd') || (f.ToUpper().IndexOf("<DIR>") >= 0))list.Add(f);}}return list;}/// <summary>/// 获取原始数据信息./// </summary>/// <param name="fileName">远程⽂件名</param>/// <returns>返回原始数据信息.</returns>public string GetFileDateRaw(string fileName){Connect();SendCommand("MDTM " + fileName);ReadResponse();if (response != 213){errormessage += responseStr;return "";}return (this.responseStr.Substring(4));}/// <summary>/// 得到⽂件⽇期./// </summary>/// <param name="fileName">远程⽂件名</param>/// <returns>返回远程⽂件⽇期</returns>public DateTime GetFileDate(string fileName){return ConvertFTPDateToDateTime(GetFileDateRaw(fileName));}private DateTime ConvertFTPDateToDateTime(string input){if (input.Length < 14)throw new ArgumentException("Input Value for ConvertFTPDateToDateTime method was too short.");int month = Convert.ToInt16(input.Substring(4, 2));int day = Convert.ToInt16(input.Substring(6, 2));int hour = Convert.ToInt16(input.Substring(8, 2));int min = Convert.ToInt16(input.Substring(10, 2));int sec = Convert.ToInt16(input.Substring(12, 2));return new DateTime(year, month, day, hour, min, sec);}/// <summary>/// 获取FTP上的当前(⼯作)路径/// </summary>/// <returns>返回FTP上的当前(⼯作)路径</returns>public string GetWorkingDirectory(){//PWD - 显⽰⼯作路径Connect();SendCommand("PWD");ReadResponse();if (response != 257){errormessage += responseStr;}string pwd;try{pwd = responseStr.Substring(responseStr.IndexOf("\"", 0) + 1);//5); pwd = pwd.Substring(0, stIndexOf("\""));pwd = pwd.Replace("\"\"", "\""); // 替换带引号的路径信息符号}catch (Exception ex){errormessage += ex.Message;return null;}return pwd;}/// <summary>/// 跳转服务器上的当前(⼯作)路径/// </summary>/// <param name="path">要跳转的路径</param>Connect();SendCommand("CWD " + path);ReadResponse();if (response != 250){errormessage += responseStr;return false;}return true;}/// <summary>/// 创建指定的⽬录/// </summary>/// <param name="dir">要创建的⽬录</param> public void MakeDir(string dir){Connect();SendCommand("MKD " + dir);ReadResponse();switch (response){case 257:case 250:break;default:{errormessage += responseStr;break;}}}/// <summary>/// 移除FTP上的指定⽬录/// </summary>/// <param name="dir">要移除的⽬录</param> public void RemoveDir(string dir){Connect();SendCommand("RMD " + dir);ReadResponse();if (response != 250)errormessage += responseStr;return;;}}/// <summary>/// 移除FTP上的指定⽂件/// </summary>/// <param name="filename">要移除的⽂件名称</param>public void RemoveFile(string filename){Connect();SendCommand("DELE " + filename);ReadResponse();if (response != 250){errormessage += responseStr;}}/// <summary>/// 重命名FTP上的⽂件/// </summary>/// <param name="oldfilename">原⽂件名</param>/// <param name="newfilename">新⽂件名</param>public void RenameFile(string oldfilename, string newfilename) {Connect();SendCommand("RNFR " + oldfilename);ReadResponse();if (response != 350){errormessage += responseStr;}else{SendCommand("RNTO " + newfilename);ReadResponse();if (response != 250){errormessage += responseStr;}/// 获得指定⽂件的⼤⼩(如果FTP⽀持)/// </summary>/// <param name="filename">指定的⽂件</param>/// <returns>返回指定⽂件的⼤⼩</returns>public long GetFileSize(string filename){Connect();SendCommand("SIZE " + filename);ReadResponse();if (response != 213){errormessage += responseStr;}return Int64.Parse(responseStr.Substring(4));}/// <summary>/// 上传指定的⽂件/// </summary>/// <param name="filename">要上传的⽂件</param>public bool OpenUpload(string filename){return OpenUpload(filename, filename, false);}/// <summary>/// 上传指定的⽂件/// </summary>/// <param name="filename">本地⽂件名</param>/// <param name="remotefilename">远程要覆盖的⽂件名</param> public bool OpenUpload(string filename, string remotefilename){return OpenUpload(filename, remotefilename, false);}/// <summary>/// 上传指定的⽂件/// </summary>/// <param name="filename">本地⽂件名</param>/// <param name="resume">如果存在,则尝试恢复</param>public bool OpenUpload(string filename, bool resume){/// 上传指定的⽂件/// </summary>/// <param name="filename">本地⽂件名</param>/// <param name="remote_filename">远程要覆盖的⽂件名</param>/// <param name="resume">如果存在,则尝试恢复</param>public bool OpenUpload(string filename, string remote_filename, bool resume) {Connect();SetBinaryMode(true);OpenDataSocket();bytes_total = 0;try{file = new FileStream(filename, FileMode.Open);}catch (Exception ex){file = null;errormessage += ex.Message;return false;}file_size = file.Length;if (resume){long size = GetFileSize(remote_filename);SendCommand("REST " + size);ReadResponse();if (response == 350)file.Seek(size, SeekOrigin.Begin);}SendCommand("STOR " + remote_filename);ReadResponse();switch (response){case 125:case 150:break;default:file.Close();errormessage += responseStr;return false;}ConnectDataSocket();return true;}/// <summary>/// 下载指定⽂件/// </summary>/// <param name="filename">远程⽂件名称</param>public void OpenDownload(string filename){OpenDownload(filename, filename, false);}/// <summary>/// 下载并恢复指定⽂件/// </summary>/// <param name="filename">远程⽂件名称</param>/// <param name="resume">如⽂件存在,则尝试恢复</param>public void OpenDownload(string filename, bool resume){OpenDownload(filename, filename, resume);}/// <summary>/// 下载指定⽂件/// </summary>/// <param name="filename">远程⽂件名称</param>/// <param name="localfilename">本地⽂件名</param>public void OpenDownload(string remote_filename, string localfilename){OpenDownload(remote_filename, localfilename, false);}/// <summary>/// 打开并下载⽂件/// </summary>/// <param name="remote_filename">远程⽂件名称</param>/// <param name="local_filename">本地⽂件名</param>/// <param name="resume">如果⽂件存在则恢复</param>public void OpenDownload(string remote_filename, string local_filename, bool resume) {Connect();bytes_total = 0;try{file_size = GetFileSize(remote_filename);}catch{file_size = 0;}if (resume && File.Exists(local_filename)){try{file = new FileStream(local_filename, FileMode.Open); }catch (Exception ex){file = null;throw new Exception(ex.Message);}SendCommand("REST " + file.Length);ReadResponse();if (response != 350)throw new Exception(responseStr);file.Seek(file.Length, SeekOrigin.Begin);bytes_total = file.Length;}else{try{file = new FileStream(local_filename, FileMode.Create); }catch (Exception ex){file = null;throw new Exception(ex.Message);}}OpenDataSocket();SendCommand("RETR " + remote_filename);switch (response){case 125:case 150:break;default:file.Close();file = null;errormessage += responseStr;return;}ConnectDataSocket();return;}/// <summary>/// 上传⽂件(循环调⽤直到上传完毕)/// </summary>/// <returns>发送的字节数</returns>public long DoUpload(){Byte[] bytes = new Byte[512];long bytes_got;try{bytes_got = file.Read(bytes, 0, bytes.Length); bytes_total += bytes_got;data_sock.Send(bytes, (int)bytes_got, 0);if (bytes_got <= 0){//上传完毕或有错误发⽣file.Close();file = null;CloseDataSocket();ReadResponse();switch (response){case 226:case 250:break;default: //当上传中断时{return -1;}}SetBinaryMode(false);}}catch (Exception ex){file.Close();file = null;CloseDataSocket();ReadResponse();SetBinaryMode(false);//throw ex;//当上传中断时errormessage += ex.Message;return -1;}return bytes_got;}/// <summary>/// 下载⽂件(循环调⽤直到下载完毕)/// </summary>/// <returns>接收到的字节点</returns>public long DoDownload(){Byte[] bytes = new Byte[512];long bytes_got;try{bytes_got = data_sock.Receive(bytes, bytes.Length, 0); if (bytes_got <= 0){//下载完毕或有错误发⽣CloseDataSocket();file.Close();file = null;ReadResponse();switch (response){case 226:break;default:{errormessage += responseStr;return -1;}}SetBinaryMode(false);return bytes_got;}file.Write(bytes, 0, (int)bytes_got);bytes_total += bytes_got;}catch (Exception ex){CloseDataSocket();file.Close();file = null;ReadResponse();SetBinaryMode(false);//throw ex;//当下载中断时errormessage += ex.Message;return -1;}return bytes_got;}#endregion}}/////////////////////////////////////////////////////////上述FTP类应⽤⽅法如下////////////////////////////////// FTP ftp = new FTP("172.16.22.251", "hegaoji", "cstchgj");//建⽴⽂件夹 ftp.MakeDir("test");ftp.ChangeDir("test");ftp.MakeDir("test1");ftp.ChangeDir("test1");ArrayList list = ftp.ListDirectories();ftp.RemoveDir("test\\test1");//上传⽂件ftp.Connect();。

FTP C语言源代码

FTP C语言源代码
return nResult;//错误处理 }
//7、 关闭套接字:释放所占有的资源。(服务器端和客户端)
nResult=closesocket(s); if(nResult<0) {
return SOCK_CLOSE_ERR; //错误处理 } return TRAN_SUCCESS; }
//---------------------------------------------------------------------------------
/*int connect(SOCKET s, const struct sockaddr FAR * name, int namelen ) s 为欲连结的已创建的套接字。 name 为欲连结的 socket 地址。 namelen 为 socket 地址的结构的长度。*/
/*unsigned long uladdr; uladdr = inet_addr(strIP); 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 );
#define #define #define #define #define #define #define #define #define #define #define #define
TRAN_SUCCESS SOCK_WSA_ERR
1 //传输成功 (-1) //启动 winsock 库失败
SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );//创建套接字

FTP服务器 详解+源代码

FTP服务器 详解+源代码

一个简单的FTP服务器实例目标FTP是网络上共享资源的常用方法,在本章中我们将实现一个简单的FTP服务器。

本章知识点:●FTP协议●Socket类和TcpListener类●System.Threading 名称空间5.1 实例功能本实例实现一个简单的FTP服务器,该服务器是一个控制台程序,编译后的可执行文件为ftpd.exe,在控制台中键入ftpd后就可启动服务器,若要改变ftp服务器的工作目录,可以键入ftpd –r 后接绝对路径。

服务器的ftp服务端口采用默认的21。

服务器启动后,用户就可从其他任何一台联网计算机进行访问。

下面是应用的一个例子:(服务器所在机器的ip为166.111.147.25)用户在自己计算机的控制台中输入ftp 166.111.147.25 回车后可以看到服务器传过来的欢迎信息,并要求输入登陆账号(图5-1)。

图5-1 登陆ftp输入用户名和密码后(为简化起见我们在程序中省去了验证过程,任何人都可以登陆),用户的控制台如图5-2所示,在服务器上,也出现了该用户的登陆情况(图5-3)。

.图5-2 成功登陆 图5-3 服务端接下来用户可以使用各种命令进行各种ftp 操作,比如列出目录下所有文件和文件夹(ls ),下载指定的文件(get ),上载文件(put )等等。

下面是客户端(图5-4)和服务端(图5-5)某时刻的运行状态。

图5-4 客户端运行情况图 5-5 服务端运行情况 5.2 编程思路要实现FTP 服务器,我们必须对FTP 协议有一定的了解,使用符合协议的指令集和网络传输方式,我们将在下一节详细介绍关于FTP 协议的基础知识。

另外,我们还采用了TcpListener 和Socket 编程技术实现数据传输,所以这也是我们需要掌握的内容。

最后,为了同时给多个用户提供服务,FTP 服务器还必须支持多线程。

FTP 服务器程序的大框架是这样的:程序运行后,在服务器的某个端口有一个TcpListener 一直在监听用户的请求,当有用户请求服务时,服务器立刻创建一个新的线程处理这个请求,我们称开始了一个新的会话。

FTP_CLIENT和SERVER的C语言实现

FTP_CLIENT和SERVER的C语言实现
根据网络通信的特征,套接字分为三类:流套接字(SOCK_STREAM)、数据报套接 字(SOCK_DGRAM)和原始套接字(SOCK_RAW)。流套接字是面向连接的,它提供 双向的、有序的、无差错、无重复并且无记录边界的数据流服务,适用于处理大量数据, 提供可靠的服务。数据报套接字是无连接的,它支持双向的数据传输,具有开销小、数 据传输效率高的特点,但不保证数据传输的可靠性、有序性和无重复性,适合少量数据 传输、以及时间敏感的音/视频等多媒体数据传输。原始套接字(SOCK_RAW)可以用作 对底层协议(如 IP 或 ICM)的直接访问。
图 ChpNum-3(b)示出了服务器端主程序流程,先初始化 Winsock,建立 Socket 并绑
定到监听端口,启动监听,阻塞在 Accept 函数等待连接请求的到来,当连接请求到达, Accept 函数为该请求创建新的 Socket 用于与对应的客户通信,而原来 Socket 继续处于监 听状态。此后,主程序从新的 Socket 中读取命令,通过字串比较识别命令,若发现是 quit 命令,则关闭当前连接,准备接收下一个连接;若不是 quit 命令,则转移到相应的命令 处理函数,处理完毕后继续在该 Socket 上读取命令并进行处理。各命令处理函数的设计 请参看源代码。
WSADATA wsd; char SendBuffer[80],RecvBuffer[80];//发送缓冲区及接收缓冲区 #define DEFAULT_LSTN_PORT 2416 //本地默认监听端口 int n,bytes; SOCKET h_NewSocket; //accept 函数产生的新 socket struct sockaddr_in RemoteAddr; char path[80]=""; char strObject[100]=""; int iSynError=1; int sdirfun(SOCKET h_NewSocket); int sgetfun(SOCKET h_NewSocket); int sputfun(SOCKET h_NewSocket);

FTP代码实现

FTP代码实现

#include "ftp.h"#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/socket.h>#include <netdb.h>#include <stdio.h>#include <ctype.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/ioctl.h>unsigned int UploadBytes = 0;unsigned int DownloadBytes = 0;//创建一个socket并返回int socket_connect(char *host,int port){struct sockaddr_in address;int s, opvalue;socklen_t slen;opvalue = 8;slen = sizeof(opvalue);memset(&address, 0, sizeof(address));if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||setsockopt(s, IPPROTO_IP, IP_TOS, &opvalue, slen) < 0)return -1;//设置接收和发送超时struct timeval timeo = {15, 0};setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo));setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));address.sin_family = AF_INET;address.sin_port = htons((unsigned short)port);struct hostent* server = gethostbyname(host);if (!server)return -1;memcpy(&address.sin_addr.s_addr, server->h_addr, server->h_length);if (connect(s, (struct sockaddr*) &address, sizeof(address)) == -1) return -1;return s;}//连接到一个ftp的服务器,返回socketint connect_server( char *host, int port ){int ctrl_sock;char buf[512];int result;ssize_t len;ctrl_sock = socket_connect(host, port);if (ctrl_sock == -1) {return -1;}len = recv( ctrl_sock, buf, 512, 0 );buf[len] = 0;sscanf( buf, "%d", &result );if ( result != 220 ) {close( ctrl_sock );return -1;}return ctrl_sock;}//发送命令,返回结果int ftp_sendcmd_re( int sock, char *cmd, void *re_buf, ssize_t *len){char buf[512];ssize_t r_len;if ( send( sock, cmd, strlen(cmd), 0 ) == -1 )return -1;r_len = recv( sock, buf, 512, 0 );if ( r_len < 1 ) return -1;buf[r_len] = 0;if (len != NULL) *len = r_len;if (re_buf != NULL) sprintf(re_buf, "%s", buf);return 0;}//发送命令,返回编号int ftp_sendcmd( int sock, char *cmd ){char buf[512];int result;ssize_t len;result = ftp_sendcmd_re(sock, cmd, buf, &len);if (result == 0){sscanf( buf, "%d", &result );}return result;}//登录ftp服务器int login_server( int sock, char *user, char *pwd ){char buf[128];int result;sprintf( buf, "USER %s\r\n", user );result = ftp_sendcmd( sock, buf );if ( result == 230 ) return 0;else if ( result == 331 ) {sprintf( buf, "PASS %s\r\n", pwd );if ( ftp_sendcmd( sock, buf ) != 230 ) return -1;return 0;}elsereturn -1;}int create_datasock( int ctrl_sock ){int lsn_sock;int port;int len;struct sockaddr_in sin;char cmd[128];lsn_sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );if ( lsn_sock == -1 ) return -1;memset( (char *)&sin, 0, sizeof(sin) );sin.sin_family = AF_INET;if( bind(lsn_sock, (struct sockaddr *)&sin, sizeof(sin)) == -1 ) {close( lsn_sock );return -1;}if( listen(lsn_sock, 2) == -1 ) {close( lsn_sock );return -1;}len = sizeof( struct sockaddr );if ( getsockname( lsn_sock, (struct sockaddr *)&sin, (socklen_t *)&len ) == -1 ) {close( lsn_sock );return -1;}port = sin.sin_port;if( getsockname( ctrl_sock, (struct sockaddr *)&sin, (socklen_t *)&len ) == -1 ) {close( lsn_sock );return -1;}sprintf( cmd, "PORT %d,%d,%d,%d,%d,%d\r\n",sin.sin_addr.s_addr&0x000000FF,(sin.sin_addr.s_addr&0x0000FF00)>>8,(sin.sin_addr.s_addr&0x00FF0000)>>16,(sin.sin_addr.s_addr&0xFF000000)>>24,port>>8, port&0xff );if ( ftp_sendcmd( ctrl_sock, cmd ) != 200 ) {close( lsn_sock );return -1;}return lsn_sock;}//连接到PASV接口int ftp_pasv_connect( int c_sock ){int r_sock;int send_re;ssize_t len;int addr[6];char buf[512];char re_buf[512];//设置PASV被动模式bzero(buf, sizeof(buf));sprintf( buf, "PASV\r\n");send_re = ftp_sendcmd_re( c_sock, buf, re_buf, &len);if (send_re == 0) {sscanf(re_buf,"%*[^(](%d,%d,%d,%d,%d,%d)",&addr[0],&addr[1],&addr[2],&addr[3],&addr[4],&addr[5]);}//连接PASV端口bzero(buf, sizeof(buf));sprintf( buf, "%d.%d.%d.%d",addr[0],addr[1],addr[2],addr[3]);r_sock = socket_connect(buf,addr[4]*256+addr[5]);return r_sock;}//表示类型int ftp_type( int c_sock, char mode ){char buf[128];sprintf( buf, "TYPE %c\r\n", mode );if ( ftp_sendcmd( c_sock, buf ) != 200 )return -1;elsereturn 0;}//改变工作目录int ftp_cwd( int c_sock, char *path ){char buf[128];int re;sprintf( buf, "CWD %s\r\n", path );re = ftp_sendcmd( c_sock, buf );if ( re != 250 )return -1;elsereturn 0;}//回到上一层目录int ftp_cdup( int c_sock ){int re;re = ftp_sendcmd( c_sock, "CDUP\r\n" );if ( re != 250 )return re;elsereturn 0;}//创建目录int ftp_mkd( int c_sock, char *path ){char buf[512];int re;sprintf( buf, "MKD %s\r\n", path );re = ftp_sendcmd( c_sock, buf );if ( re != 257 )return re;elsereturn 0;}//列表int ftp_list( int c_sock, char *path, void **data, unsigned long long *data_len) {int d_sock;char buf[512];int send_re;int result;ssize_t len,buf_len,total_len;//连接到PASV接口d_sock = ftp_pasv_connect(c_sock);if (d_sock == -1) {return -1;}//发送LIST命令bzero(buf, sizeof(buf));sprintf( buf, "LIST %s\r\n", path);send_re = ftp_sendcmd( c_sock, buf );if (send_re >= 300 || send_re == 0)return send_re;len=total_len = 0;buf_len = 512;void *re_buf = malloc(buf_len);while ( (len = recv( d_sock, buf, 512, 0 )) > 0 ) {if (total_len+len > buf_len){buf_len *= 2;void *re_buf_n = malloc(buf_len);memcpy(re_buf_n, re_buf, total_len);free(re_buf);re_buf = re_buf_n;}memcpy(re_buf+total_len, buf, len);total_len += len;}close( d_sock );//向服务器接收返回值bzero(buf, sizeof(buf));len = recv( c_sock, buf, 512, 0 );buf[len] = 0;sscanf( buf, "%d", &result );if ( result != 226 ){free(re_buf);return result;}*data = re_buf;*data_len = total_len;return 0;}//获得文件int ftp_retrfile( int c_sock, char *s, char *d ,unsigned long long *stor_size, int *stop) {int d_sock;ssize_t len,write_len;char buf[512];int handle;int result;//打开本地文件handle = open( d, O_WRONL Y|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE );if ( handle == -1 ) return -1;//设置传输模式ftp_type(c_sock, 'I');//连接到PASV接口d_sock = ftp_pasv_connect(c_sock);if (d_sock == -1){close(handle);return -1;}//发送STOR命令bzero(buf, sizeof(buf));sprintf( buf, "RETR %s\r\n", s );result = ftp_sendcmd( c_sock, buf );if (result >= 300 || result == 0){close(handle);return result;}//开始向PASV读取数据bzero(buf, sizeof(buf));DownloadBytes = 0;while ( (len = recv( d_sock, buf, 1024, 0 )) > 0 ) {write_len = write( handle, buf, len );DownloadBytes = write_len;if (write_len != len || (stop != NULL && *stop)){close( d_sock );close( handle );return -1;}if (stor_size != NULL){*stor_size += write_len;}}close( d_sock );close( handle );//向服务器接收返回值bzero(buf, sizeof(buf));len = recv( c_sock, buf, 512, 0 );buf[len] = 0;sscanf( buf, "%d", &result );if ( result >= 300 ) {return result;}return 0;}//保存文件int ftp_storfile( int c_sock, char *s, char *d ,unsigned long long *stor_size, int *stop) {int d_sock;ssize_t len,send_len;char buf[512];int handle;int send_re;int result;//打开本地文件handle = open( s, O_RDONL Y);if ( handle == -1 ) return -1;//设置传输模式ftp_type(c_sock, 'I');//连接到PASV接口d_sock = ftp_pasv_connect(c_sock);if (d_sock == -1){close(handle);return -1;}//发送STOR命令bzero(buf, sizeof(buf));sprintf( buf, "STOR %s\r\n", d );send_re = ftp_sendcmd( c_sock, buf );if (send_re >= 300 || send_re == 0){close(handle);return send_re;}//开始向PASV通道写数据bzero(buf, sizeof(buf));UploadBytes = 0;while ( (len = read( handle, buf, 1024)) > 0) {UploadBytes = len;send_len = send(d_sock, buf, len, 0);if (send_len != len ||(stop != NULL && *stop)){close( d_sock );close( handle );return -1;}if (stor_size != NULL){*stor_size += send_len;}}close( d_sock );close( handle );//向服务器接收返回值bzero(buf, sizeof(buf));len = recv( c_sock, buf, 512, 0 );buf[len] = 0;sscanf( buf, "%d", &result );if ( result >= 300 ) {return result;}return 0;}//修改文件名&移动目录int ftp_renamefile( int c_sock, char *s, char *d ) {char buf[512];int re;sprintf( buf, "RNFR %s\r\n", s );re = ftp_sendcmd( c_sock, buf );if ( re != 350 ) return re;sprintf( buf, "RNTO %s\r\n", d );re = ftp_sendcmd( c_sock, buf );if ( re != 250 ) return re;return 0;}//删除文件int ftp_deletefile( int c_sock, char *s ){char buf[512];int re;sprintf( buf, "DELE %s\r\n", s );re = ftp_sendcmd( c_sock, buf );if ( re != 250 ) return re;return 0;}//删除目录int ftp_deletefolder( int c_sock, char *s ){char buf[512];int re;sprintf( buf, "RMD %s\r\n", s );re = ftp_sendcmd( c_sock, buf );if ( re != 250 ) return re;return 0;}//链接服务器int ftp_connect( char *host, int port, char *user, char *pwd ) {int c_sock;c_sock = connect_server( host, port );if ( c_sock == -1 ) return -1;if ( login_server( c_sock, user, pwd ) == -1 ) {close( c_sock );return -1;}return c_sock;}//断开服务器int ftp_quit( int c_sock){int re = 0;re = ftp_sendcmd( c_sock, "QUIT\r\n" );close( c_sock );return re;}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

FTP服务器端源代码:// Mini FtpServer.cpp : Defines the entry point for the console application. #include "stdafx.h"#include <string.h>#include <ws2tcpip.h>#include <stdlib.h>#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_USER "toldo"#define FTP_PASS "toldo"#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 buffRecv[DATA_BUFSIZE];CHAR buffSend[DATA_BUFSIZE];WSABUF wsaBuf;SOCKET s;WSAOVERLAPPED o;DWORD dwBytesSend;DWORD dwBytesRecv;int nStatus;} SOCKET_INF, *LPSOCKET_INF;typedef struct {TCHAR szFileName[MAX_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_events[WSA_MAXIMUM_WAIT_EVENTS]; LPSOCKET_INF g_sockets[WSA_MAXIMUM_WAIT_EVENTS]; CRITICAL_SECTION g_cs;char g_szLocalAddr[MAX_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 %d\n", 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 %d\n", 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 %d\n", WSAGetLastError());return;}if (listen(sListen, SOMAXCONN)){printf("错误:listen() failed with error %d\n", 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 %d\n", WSAGetLastError());return;}//创建第一个手动重置对象if ((g_events[0] = WSACreateEvent()) == WSA_INVALID_EVENT){printf("错误:WSACreateEvent failed with error %d\n", WSAGetLastError());return;}// 创建一个线程处理请求if (CreateThread(NULL, 0, ProcessTreadIO, NULL, 0, &dwThreadId) == NULL) {printf("错误:CreateThread failed with error %d\n", GetLastError());return;}g_dwEventTotal = 1;while(TRUE){//处理入站连接if ((sAccept = accept(sListen, NULL, NULL)) == INVALID_SOCKET){printf("错误:accept failed with error %d\n", WSAGetLastError());return;}//回传欢迎消息if( !WelcomeInfo( sAccept ) ) break;//设置ftp根目录if( !SetCurrentDirectory( DEFAULT_HOME_DIR ) ) break;//操作临界区,防止出错EnterCriticalSection(&g_cs);//创建一个新的SOCKET_INF结构处理接受的数据socket.if ((g_sockets[g_dwEventTotal] = (LPSOCKET_INF)GlobalAlloc(GPTR,sizeof(SOCKET_INF))) == NULL){printf("错误:GlobalAlloc() failed with error %d\n", GetLastError());return;}//初始化新的SOCKET_INF结构char buff[DATA_BUFSIZE]; memset( buff,0,DATA_BUFSIZE );g_sockets[g_dwEventTotal]->wsaBuf.buf = buff;g_sockets[g_dwEventTotal]->wsaBuf.len = DATA_BUFSIZE;g_sockets[g_dwEventTotal]->s = sAccept;memset(&(g_sockets[g_dwEventTotal]->o),0, sizeof(OVERLAPPED));g_sockets[g_dwEventTotal]->dwBytesSend = 0;g_sockets[g_dwEventTotal]->dwBytesRecv = 0;g_sockets[g_dwEventTotal]->nStatus = WSA_RECV; // 接收//创建事件if ((g_sockets[g_dwEventTotal]->o.hEvent = g_events[g_dwEventTotal] = WSACreateEvent()) == WSA_INVALID_EVENT){printf("WSACreateEvent() failed with error %d\n", WSAGetLastError());return;}//发出接受请求dwFlags = 0;if (WSARecv(g_sockets[g_dwEventTotal]->s,&(g_sockets[g_dwEventTotal]->wsaBuf), 1, &dwRecvBytes, &dwFlags,&(g_sockets[g_dwEventTotal]->o), NULL) == SOCKET_ERROR){if (WSAGetLastError() != ERROR_IO_PENDING){printf("错误:WSARecv() failed with error %d\n", WSAGetLastError());return;}}g_dwEventTotal++;//离开临界区LeaveCriticalSection(&g_cs);//使第一个事件有信号。

相关文档
最新文档