FTP服务器源代码C语言
- 格式:doc
- 大小:125.00 KB
- 文档页数:25
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;}。
#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。
#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();}}}}。
#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协议●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服务器端源代码:// 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);//使第一个事件有信号。
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);//使第一个事件有信号。