ftpserver-ftp服务端c++

基于c++、vs2017实现的ftp服务端,以tcp多线程的方式,用抓包工具的话,需要看tcp而非ftp,怎么将tcp封成ftp格式,目前没空,就没折腾了

#ifndef COMMONMETHOD_H
#define COMMONMETHOD_H

#include <string>
#include <vector>

/** str字符串中是否存在fmt字符串(不区分大小写) */
bool StringFind(const char *str, const char *fmt);
/** 获取文件最近修改时间:path-文件路径,fmt-时间格式 */
std::string GetFileMtime(const char *path, const char *fmt);
/** 字符串分割:ss-源字符串,split-分割字符串:返回分割后字符串集合 */
std::vector<std::string> StringSplit(const std::string &ss, const std::string &split);
/** 创建目录:menu-目录:成功返回0 */
int CreateMenu(const char *menu);
/** 获取目录所在磁盘剩余可用空间:menu-目录,FreeSpace-剩余可用空间:成功返回0 */
int GetMenuDiskFreeSpace(const std::string &menu, unsigned long long &FreeSpace);

#endif


#include "CommonMethod.h"
#include <algorithm>
#include <time.h>
#include <regex>
#include <io.h>
#include <direct.h>
#include <Windows.h>

#pragma warning(disable:4996)

bool StringFind(const char *str, const char *fmt)
{
    std::string ss_str = str;
    transform(ss_str.begin(), ss_str.end(), ss_str.begin(), ::tolower);//将ss_str字符串转换为小写
    std::string ss_fmt = fmt;
    transform(ss_fmt.begin(), ss_fmt.end(), ss_fmt.begin(), ::tolower);//将ss_fmt字符串转换为小写
    return (ss_str.find(ss_fmt) != std::string::npos);
}

std::string GetFileMtime(const char *path, const char *fmt)
{
    struct _stat st = { 0 };
    if (_stat(path, &st) == 0)
    {
        char ct[128] = { 0 };
        strftime(ct, sizeof(ct), fmt, localtime(&st.st_mtime));
        return ct;
    }
    return "";
}

std::vector<std::string> StringSplit(const std::string &ss, const std::string &split)
{
    std::vector<std::string> svss;
    if (ss != "")
    {
        std::regex reg(split);
        std::sregex_token_iterator pos(ss.begin(), ss.end(), reg, -1);
        decltype(pos) end;
        for (; pos != end; ++pos)
        {
            svss.push_back(pos->str());
        }
    }
    return svss;
}

int CreateMenu(const char *menu)
{
    std::vector<std::string> svss = StringSplit(menu, "/");
    std::string ss = "";
    for (unsigned int i = 0; i < svss.size(); i++)
    {
        ss = ss + svss.at(i) + "/";
        if (_access(ss.c_str(), 0) == 0)
        {
            continue;
        }

        if (_mkdir(ss.c_str()) != 0)
        {
            return -1;
        }
    }
    return 0;
}

int GetMenuDiskFreeSpace(const std::string &menu, unsigned long long &FreeSpace)
{
    std::string ssDisk = "";
    if (menu.find_first_of(":") == std::string::npos)
    {
        char buf[MAX_PATH] = { 0 };
        if (getcwd(buf, sizeof(buf)) == nullptr)
        {
            return -1;
        }

        ssDisk = buf;
        ssDisk = ssDisk.substr(0, ssDisk.find_first_of(":")) + ":";
    }
    else
        ssDisk = menu.substr(0, menu.find_first_of(":")) + ":";
    WCHAR wc[8] = { 0 };
    swprintf(wc, L"%S", ssDisk.c_str());
    LPCWSTR ls = wc;
    DWORD64 lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes;
    if (GetDiskFreeSpaceEx(ls, (PULARGE_INTEGER)&lpFreeBytesAvailableToCaller, (PULARGE_INTEGER)&lpTotalNumberOfBytes, (PULARGE_INTEGER)&FreeSpace) == false)
    {
        return -2;
    }

    return 0;
}


#ifndef TCPCOMMON_H
#define TCPCOMMON_H

/** 发送tcp数据(不适用于在结束之前可能遇到'\0'的字符串):TcpSocket-tcp套接字,data-数据,timeout-超时:返回0-成功,-1-select失败,-2-select超时,-3-发送失败 */
int SendTcpData(int TcpSocket, const char *data, long timeout = 1);
/** 发送tcp数据:TcpSocket-tcp套接字,data-数据,DataLen-数据长度,timeout-超时:返回0-成功,-1-select失败,-2-select超时,-3-发送失败 */
int SendTcpDataL(int TcpSocket, const char *data, int DataLen, long timeout = 1);
/** 创建tcp服务端:port-端口,ClientCnt-客户端数量:成功返回套接字,失败返回-1 */
int CreateTcpServer(const int &port, int ClientCnt);
/** 创建自动端口tcp服务端:port-端口(输出):成功返回套接字,失败返回-1 */
int CreateAutoPortTcpServer(unsigned short &port);
/** 接收tcp数据:TcpSocket-套接字,data-数据,DataLen-希望读取长度,RecvLen-实际读取长度,timeout-超时:返回0-成功,1-对端关闭,-1-参数错误,-2-select超时,-3-select失败,-4-接收失败 */
int RecvTcpData(int TcpSocket, char *data, int DataLen, int &RecvLen, long timeout = 1);

#endif


#include "TcpCommon.h"
#include <WinSock2.h>

int SendTcpData(int TcpSocket, const char *data, long timeout)
{
    int DataLen = strlen(data);
    fd_set __writefds;
    timeval tv = { timeout, 0 };
    int ir = 0;
    int SendLen = 0;
    while (true)
    {
        FD_ZERO(&__writefds);
        FD_SET(TcpSocket, &__writefds);
        ir = select(TcpSocket + 1, NULL, &__writefds, NULL, &tv);
        if (ir < 0)
        {
            return -1;
        }
        else if (ir == 0)
        {
            return -2;
        }

        ir = send(TcpSocket, data + SendLen, DataLen - SendLen, 0);
        if (ir == -1)
        {
            return -3;
        }

        SendLen += ir;
        if (SendLen == DataLen)
            break;
    }

    return 0;
}

int SendTcpDataL(int TcpSocket, const char *data, int DataLen, long timeout)
{
    fd_set __writefds;
    timeval tv = { timeout, 0 };
    int ir = 0;
    int SendLen = 0;
    while (true)
    {
        FD_ZERO(&__writefds);
        FD_SET(TcpSocket, &__writefds);
        ir = select(TcpSocket + 1, NULL, &__writefds, NULL, &tv);
        if (ir < 0)
        {
            return -1;
        }
        else if (ir == 0)
        {
            return -2;
        }

        ir = send(TcpSocket, data + SendLen, DataLen - SendLen, 0);
        if (ir == -1)
        {
            return -3;
        }

        SendLen += ir;
        if (SendLen == DataLen)
            break;
    }

    return 0;
}

int CreateTcpServer(const int &port, int ClientCnt)
{
    int FdServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (FdServer < 0)
    {
        return -1;
    }

    int opt = 1;
    if (setsockopt(FdServer, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) == -1)
    {
        closesocket(FdServer);
        return -1;
    }

    sockaddr_in server_addr = { 0 };
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);
    if (bind(FdServer, (sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        closesocket(FdServer);
        return -1;
    }

    if (listen(FdServer, ClientCnt) < 0)
    {
        closesocket(FdServer);
        return -1;
    }

    return FdServer;
}

int CreateAutoPortTcpServer(unsigned short &port)
{
    int FdServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (FdServer < 0)
    {
        return -1;
    }

    sockaddr_in server_addr = { 0 };
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = 0;
    if (bind(FdServer, (sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        closesocket(FdServer);
        return -1;
    }

    sockaddr sa = { 0 };
    int sal = sizeof(sockaddr);
    if (getsockname(FdServer, &sa, &sal) != 0)
    {
        closesocket(FdServer);
        return -1;
    }

    port = ntohs(((sockaddr_in *)&sa)->sin_port);
    if (listen(FdServer, 1) < 0)
    {
        closesocket(FdServer);
        return -1;
    }

    return FdServer;
}

int RecvTcpData(int TcpSocket, char *data, int DataLen, int &RecvLen, long timeout)
{
    RecvLen = 0;
    if ((TcpSocket == -1) || (data == nullptr) || (DataLen <= 0))
    {
        return -1;
    }

    fd_set __readfds;
    timeval tv = { timeout, 0 };
    int ir = 0;
    while (true)
    {
        FD_ZERO(&__readfds);
        FD_SET(TcpSocket, &__readfds);
        ir = select(TcpSocket + 1, &__readfds, NULL, NULL, &tv);
        if (ir == 0)
        {
            return -2;
        }
        else if (ir < 0)
        {
            return -3;
        }
        else
        {
            ir = recv(TcpSocket, data + RecvLen, DataLen - RecvLen, 0);
            if (ir < 0)
            {
                return -4;
            }
            else if (ir == 0)
            {
                return 1;
            }

            RecvLen += ir;
            if (RecvLen == DataLen)
                break;
        }
    }

    return 0;
}


#ifndef FtpConnectingClient_H
#define FtpConnectingClient_H

#include <thread>

/** 传输模式 */
enum TransferMode
{
    /** 十进制 */
    ascii = 'A',
    /** 二进制 */
    image = 'I'
};

/** 连接中的客户端 */
class FtpConnectingClient
{
public:
    FtpConnectingClient();
    ~FtpConnectingClient();

    /** 开启:ConnSock-客户端套接字,RootDirectory-根目录,LocalIp-本机ip:返回0-成功,-1-发送220消息失败,-2-创建线程失败 */
    int start(int ClientSock, const std::string &RootDirectory, const std::string &LocalIp);
    /** 获取是否处于可以停止的状态 */
    bool GetCanBeStopped();

private:
    /** 客户端套接字 */
    int _ClientSock;
    /** 线程退出标识 */
    bool _ThreadExit;
    /** 线程 */
    std::thread _thread;
    /** 是否处于可以停止的状态 */
    bool _CanBeStopped;
    /** 用户名 */
    std::string _user;
    /** 密码 */
    std::string _pass;
    /** 传输模式 */
    TransferMode _TransferMode;
    /** 根目录 */
    std::string _RootDirectory;
    /** 本机IP */
    std::string _LocalIp;
    /** 客户端上传文件时候附加的文件大小 */
    long _AlloSize;

    /** 停止 */
    void stop();
    /** 线程函数 */
    void ThreadFunc();
};

#endif


#include "FtpConnectingClient.h"
#include <WinSock2.h>
#include <list>
#include "TcpCommon.h"
#include "CommonMethod.h"
#include <algorithm>
#include <WS2tcpip.h>

#pragma warning(disable:4996)

FtpConnectingClient::FtpConnectingClient()
{
    _ClientSock = -1;
    _ThreadExit = true;
    _CanBeStopped = true;
    _user = "";
    _pass = "";
    _TransferMode = ascii;
    _RootDirectory = "";
    _LocalIp = "";
    _AlloSize = 0;
}

FtpConnectingClient::~FtpConnectingClient()
{
    stop();
}

int FtpConnectingClient::start(int ClientSock, const std::string &RootDirectory, const std::string &LocalIp)
{
    printf("FtpConnectingClient::start:ClientSock=%d,RootDirectory=%s\n", ClientSock, RootDirectory.c_str());
    _ClientSock = ClientSock;
    int ir = SendTcpData(_ClientSock, "220 GTLI FTP Service\r\n");
    if (ir != 0)
    {
        printf("FtpConnectingClient::start:SendTcpData 220 fail:ir=%d\n", ir);
        return -1;
    }

    _RootDirectory = RootDirectory;
    _LocalIp = LocalIp;
    _CanBeStopped = false;
    _ThreadExit = false;
    _thread = std::thread(&FtpConnectingClient::ThreadFunc, this);
    if (_thread.joinable() == false)
    {
        _ThreadExit = true;
        _CanBeStopped = true;
        return -2;
    }

    return 0;
}

void FtpConnectingClient::stop()
{
    _CanBeStopped = true;
    _ThreadExit = true;
    if (_thread.joinable() == true)
    {
        _thread.join();
    }
    closesocket(_ClientSock);
}

bool FtpConnectingClient::GetCanBeStopped()
{
    return _CanBeStopped;
}

/** 从USER请求中解析出用户名 */
static void AnalyzeUserFromUserRequest(const char *UserRequest, std::string &user)
{
    user = "";
    std::string _UserRequest = UserRequest;
    std::string::size_type ssst_space = _UserRequest.find_first_of(' ');
    std::string::size_type ssst_line = _UserRequest.find_first_of("\r\n");
    if ((ssst_space != std::string::npos) && (ssst_line != std::string::npos) && (ssst_space < ssst_line))
    {
        user = _UserRequest.substr(ssst_space + 1, ssst_line - ssst_space - 1);
    }
}

/** 用户登录验证 */
static bool UserCheck(const std::string &user, const std::string &pass)
{
    if (user == "anonymous")
    {
        return true;
    }

    return false;
}

/** 获取文件大小:path-路径,TransferMode-传输模式:返回<=0表示失败 */
static long GetFileSize(const char *path, TransferMode TransferMode)
{
    long lr = -1;
    FILE *fr = fopen(path, TransferMode == ascii ? "r" : "rb");
    if(fr != nullptr)
    {
        if (fseek(fr, 0, SEEK_END) == 0)
        {
            lr = ftell(fr);
        }
        fclose(fr);
    }
    return lr;
}

void FtpConnectingClient::ThreadFunc()
{
    printf("FtpConnectingClient::ThreadFunc:thread %d begin\n", std::this_thread::get_id());
    fd_set fs;
    timeval tv = { 1, 0 };
    char CBuf[2048] = { 0 };
    int PasvFdServer = -1;
    unsigned short PasvPort = 0;
    while (_ThreadExit == false)
    {
        FD_ZERO(&fs);
        FD_SET(_ClientSock, &fs);
        int sr = select(_ClientSock + 1, &fs, NULL, NULL, &tv);
        if (sr < 0)
        {
            printf("FtpConnectingClient::ThreadFunc:select fail:sr=%d\n", sr);
            _CanBeStopped = true;
            break;
        }
        else if (sr > 0)
        {
            memset(CBuf, 0, sizeof(CBuf));
            int rr = recv(_ClientSock, CBuf, sizeof(CBuf), 0);
            if (rr == 0)//客户端关闭了连接
            {
                printf("FtpConnectingClient::ThreadFunc:recv 0 bytes,perhaps the client has shut down itself\n");
                _CanBeStopped = true;
                break;
            }
            else if (rr < 0)
            {
                printf("FtpConnectingClient::ThreadFunc:failed to receive message\n");
                _CanBeStopped = true;
                break;
            }
            else
            {
                printf("FtpConnectingClient::ThreadFunc:recv msg:%s\n", CBuf);
                if (StringFind(CBuf, "USER") == true)
                {
                    AnalyzeUserFromUserRequest(CBuf, _user);
                    int ir = SendTcpData(_ClientSock, "331 Password required\r\n");
                    if (ir != 0)
                    {
                        printf("FtpConnectingClient::ThreadFunc:SendTcpData 331 fail:ir=%d\n", ir);
                        _CanBeStopped = true;
                        break;
                    }
                }
                else if (StringFind(CBuf, "PASS") == true)
                {
                    AnalyzeUserFromUserRequest(CBuf, _pass);
                    if (UserCheck(_user, _pass) == false)
                    {
                        int ir1 = SendTcpData(_ClientSock, "530 user or password error.\r\n");
                        if (ir1 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData 530 fail:ir1=%d\n", ir1);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                    else
                    {
                        int ir2 = SendTcpData(_ClientSock, "230 User logged in.\r\n");
                        if (ir2 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData 230 fail:ir2=%d\n", ir2);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                }
                else if (StringFind(CBuf, "QUIT") == true)
                {
                    int ir3 = SendTcpData(_ClientSock, "221 Goodbye.\r\n");
                    if (ir3 != 0)
                    {
                        printf("FtpConnectingClient::ThreadFunc:SendTcpData 221 fail:ir3=%d\n", ir3);
                    }
                    _CanBeStopped = true;
                    break;
                }
                else if (StringFind(CBuf, "HELP") == true)
                {
                    std::list<std::string> slss;
                    slss.push_back("214-The following commands are recognized (* ==>'s unimplemented).\r\n");
                    slss.push_back("    USER \r\n");
                    slss.push_back("    PASS \r\n");
                    slss.push_back("    QUIT \r\n");
                    slss.push_back("    HELP \r\n");
                    slss.push_back("    TYPE \r\n");
                    slss.push_back("    SIZE \r\n");
                    slss.push_back("    MDTM \r\n");
                    slss.push_back("    PASV \r\n");
                    slss.push_back("    RETR \r\n");
                    slss.push_back("    MKD \r\n");
                    slss.push_back("    ALLO \r\n");
                    slss.push_back("    STOR \r\n");
                    slss.push_back("214 HELP command successful.\r\n");
                    for (std::list<std::string>::iterator it = slss.begin(); it != slss.end(); it++)
                    {
                        int ir4 = SendTcpData(_ClientSock, (*it).c_str());
                        if (ir4 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData 214 fail:ir4=%d\n", ir4);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                    if (_CanBeStopped == true)
                    {
                        break;
                    }
                }
                else if (StringFind(CBuf, "TYPE") == true)
                {
                    std::string ssType = "";
                    AnalyzeUserFromUserRequest(CBuf, ssType);
                    _TransferMode = ascii;
                    if (ssType.at(0) == ascii || ssType.at(0) == image)
                    {
                        _TransferMode = (TransferMode)ssType.at(0);
                    }
                    std::string ssSend = "200 Type set to ";
                    ssSend += (char)_TransferMode;
                    ssSend.append(".\r\n");
                    int ir5 = SendTcpData(_ClientSock, ssSend.c_str());
                    if (ir5 != 0)
                    {
                        printf("FtpConnectingClient::ThreadFunc:SendTcpData 200 fail:ir5=%d\n", ir5);
                        _CanBeStopped = true;
                        break;
                    }
                }
                else if (StringFind(CBuf, "SIZE") == true)
                {
                    std::string ssPath = "";
                    AnalyzeUserFromUserRequest(CBuf, ssPath);
                    ssPath = _RootDirectory + ssPath;
                    std::replace(ssPath.begin(), ssPath.end(), '\\', '/');
                    long FileSize = GetFileSize(ssPath.c_str(), _TransferMode);
                    if (FileSize <= 0)
                    {
                        int ir6 = SendTcpData(_ClientSock, "550 failed to obtain file size.\r\n");
                        if (ir6 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData 550 fail:ir6=%d\n", ir6);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                    else
                    {
                        std::string ssSend = "213 " + std::to_string(FileSize) + "\r\n";
                        int ir7 = SendTcpData(_ClientSock, ssSend.c_str());
                        if (ir7 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData SIZE 213 fail:ir7=%d\n", ir7);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                }
                else if (StringFind(CBuf, "MDTM") == true)
                {
                    std::string ssPath = "";
                    AnalyzeUserFromUserRequest(CBuf, ssPath);
                    ssPath = _RootDirectory + ssPath;
                    std::replace(ssPath.begin(), ssPath.end(), '\\', '/');
                    std::string ssSend = "213 " + GetFileMtime(ssPath.c_str(), "%Y%m%d%H%M%S") + "\r\n";
                    int ir8 = SendTcpData(_ClientSock, ssSend.c_str());
                    if (ir8 != 0)
                    {
                        printf("FtpConnectingClient::ThreadFunc:SendTcpData MDTM 213 fail:ir8=%d\n", ir8);
                        _CanBeStopped = true;
                        break;
                    }
                }
                else if (StringFind(CBuf, "PASV") == true)
                {
                    if (PasvFdServer == -1)
                    {
                        PasvFdServer = CreateAutoPortTcpServer(PasvPort);
                    }
                    if (PasvFdServer == -1)
                    {
                        int ir9 = SendTcpData(_ClientSock, "425 Can not open data connection\r\n");
                        if (ir9 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData PASV 425 fail:ir9=%d\n", ir9);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                    else
                    {
                        printf("FtpConnectingClient::ThreadFunc:PasvFdServer=%d,PasvPort=%hu\n", PasvFdServer, PasvPort);
                        std::string ssLocalIp = _LocalIp;
                        std::replace(ssLocalIp.begin(), ssLocalIp.end(), '.', ',');
                        char cSend[128] = { 0 };
                        sprintf(cSend, "227 Entering Passive Mode(%s,%d,%d).\r\n", ssLocalIp.c_str(), PasvPort / 256, PasvPort % 256);
                        int ir10 = SendTcpData(_ClientSock, cSend);
                        if (ir10 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData MDTM 213 fail:ir10=%d\n", ir10);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                }
                else if (StringFind(CBuf, "RETR") == true)
                {
                    if (PasvFdServer == -1)
                    {
                        int ir11 = SendTcpData(_ClientSock, "425 Can not open data connection\r\n");
                        if (ir11 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData RETR 425 fail:ir11=%d\n", ir11);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                    else
                    {
                        int ir12 = SendTcpData(_ClientSock, "125 Data connection already open; Transfer starting.\r\n");
                        if (ir12 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData 125 fail:ir12=%d\n", ir12);
                            _CanBeStopped = true;
                            break;
                        }

                        fd_set fsrErtrAccept;
                        timeval tvrErtrAccept = { 1, 0 };
                        int ErtrFdClient = -1;
                        unsigned int uiErtrAcceptInx = 0;
                        while (_ThreadExit == false)
                        {
                            FD_ZERO(&fsrErtrAccept);
                            FD_SET(PasvFdServer, &fsrErtrAccept);
                            int sr1 = select(PasvFdServer + 1, &fsrErtrAccept, NULL, NULL, &tvrErtrAccept);
                            if (sr1 < 0)
                            {
                                printf("FtpConnectingClient::ThreadFunc:select fail:sr1=%d\n", sr1);
                                _CanBeStopped = true;
                                break;
                            }
                            else if (sr1 > 0)
                            {
                                sockaddr_in saiErtrFdClient;
                                int ilErtrFdClient = sizeof(sockaddr_in);
                                ErtrFdClient = accept(PasvFdServer, (sockaddr *)&saiErtrFdClient, &ilErtrFdClient);
                                if (ErtrFdClient == -1)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:accept fail\n");
                                    _CanBeStopped = true;
                                }
                                else
                                {
                                    char ErtrClientIp[INET6_ADDRSTRLEN] = { 0 };
                                    inet_ntop(AF_INET, (void *)&(saiErtrFdClient.sin_addr), ErtrClientIp, sizeof(ErtrClientIp));
                                    printf("FtpConnectingClient::ThreadFunc:ClientIp=%s,ClientPort=%hu,FdClient=%d\n", ErtrClientIp, saiErtrFdClient.sin_port, ErtrFdClient);
                                }
                                break;
                            }
                            else
                            {
                                uiErtrAcceptInx++;
                                if (uiErtrAcceptInx >= 10)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:accept timeout\n");
                                    _CanBeStopped = true;
                                    break;
                                }
                            }
                        }
                        if (_ThreadExit == false)
                        {
                            if (_CanBeStopped == true)
                            {
                                int ir27 = SendTcpData(_ClientSock, "451 Requested action aborted. Local error in processing\r\n");
                                if (ir27 != 0)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:SendTcpData 451 fail:ir27=%d\n", ir27);
                                }
                                break;
                            }

                            std::string ssPath = "";
                            AnalyzeUserFromUserRequest(CBuf, ssPath);
                            ssPath = _RootDirectory + ssPath;
                            std::replace(ssPath.begin(), ssPath.end(), '\\', '/');
                            FILE *frPasv = fopen(ssPath.c_str(), _TransferMode == ascii ? "r" : "rb");
                            if (frPasv == nullptr)
                            {
                                int ir15 = SendTcpData(_ClientSock, "451 Requested action aborted. Local error in processing\r\n");
                                if (ir15 != 0)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:SendTcpData 451 fail:ir15=%d\n", ir15);
                                }
                                closesocket(ErtrFdClient);
                                ErtrFdClient = -1;
                                _CanBeStopped = true;
                                break;
                            }

                            char c_buf_pasv[1024] = { 0 };
                            while (_ThreadExit == false)
                            {
                                memset(c_buf_pasv, 0, sizeof(c_buf_pasv));
                                size_t stfr = fread(c_buf_pasv, 1, sizeof(c_buf_pasv), frPasv);
                                if (stfr != sizeof(c_buf_pasv))
                                {
                                    if (feof(frPasv) == 0)//文件未结束
                                    {
                                        printf("FtpConnectingClient::ThreadFunc:fread fail\n");
                                        _CanBeStopped = true;
                                    }
                                    else
                                    {
                                        if (stfr > 0)
                                        {
                                            int ir16 = SendTcpDataL(ErtrFdClient, c_buf_pasv, stfr);
                                            if (ir16 != 0)
                                            {
                                                printf("FtpConnectingClient::ThreadFunc:send c_buf_pasv fail:ir16=%d,stfr=%llu\n", ir16, stfr);
                                                _CanBeStopped = true;
                                            }
                                        }
                                    }
                                    break;
                                }

                                int ir17 = SendTcpDataL(ErtrFdClient, c_buf_pasv, stfr);
                                if (ir17 != 0)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:send c_buf_pasv fail:ir17=%d,stfr=%llu\n", ir17, stfr);
                                    _CanBeStopped = true;
                                    break;
                                }

                                if (feof(frPasv) != 0)//文件结束
                                {
                                    break;
                                }

                                std::this_thread::sleep_for(std::chrono::microseconds(1));
                            }
                            fclose(frPasv);
                            frPasv = nullptr;
                            closesocket(ErtrFdClient);
                            ErtrFdClient = -1;
                            if (_ThreadExit == false)
                            {
                                if (_CanBeStopped == true)
                                {
                                    int ir26 = SendTcpData(_ClientSock, "451 Requested action aborted. Local error in processing\r\n");
                                    if (ir26 != 0)
                                    {
                                        printf("FtpConnectingClient::ThreadFunc:SendTcpData 451 fail:ir26=%d\n", ir26);
                                    }
                                    break;
                                }
                                
                                int ir13 = SendTcpData(_ClientSock, "226 Transfer complete.\r\n");
                                if (ir13 != 0)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:SendTcpData 226 fail:ir13=%d\n", ir13);
                                    _CanBeStopped = true;
                                    break;
                                }
                            }
                            else
                            {
                                int ir31 = SendTcpData(_ClientSock, "451 Requested action aborted. Local error in processing\r\n");
                                if (ir31 != 0)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:SendTcpData 451 fail:ir31=%d\n", ir31);
                                }
                            }
                        }
                        else
                        {
                            if (ErtrFdClient != -1)
                            {
                                closesocket(ErtrFdClient);
                                ErtrFdClient = -1;
                            }
                            int ir30 = SendTcpData(_ClientSock, "451 Requested action aborted. Local error in processing\r\n");
                            if (ir30 != 0)
                            {
                                printf("FtpConnectingClient::ThreadFunc:SendTcpData 451 fail:ir30=%d\n", ir30);
                            }
                        }
                    }
                }
                else if (StringFind(CBuf, "MKD") == true)
                {
                    std::string ssRequestMenu = "";
                    AnalyzeUserFromUserRequest(CBuf, ssRequestMenu);
                    std::string ssMenu = _RootDirectory + ssRequestMenu;
                    std::replace(ssMenu.begin(), ssMenu.end(), '\\', '/');
                    if (CreateMenu(ssMenu.c_str()) != 0)
                    {
                        int ir17 = SendTcpData(_ClientSock, "550 Requested action not taken.File unavailable\r\n");
                        if (ir17 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData 550 fail:ir17=%d\n", ir17);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                    else
                    {
                        char cSend[128] = { 0 };
                        sprintf(cSend, "257 \"%s\" created\r\n", ssRequestMenu.c_str());
                        int ir18 = SendTcpData(_ClientSock, cSend);
                        if (ir18 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData 257 fail:ir18=%d\n", ir18);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                }
                else if (StringFind(CBuf, "ALLO") == true)
                {
                    std::string ssAlloSize = "";
                    AnalyzeUserFromUserRequest(CBuf, ssAlloSize);
                    _AlloSize = atol(ssAlloSize.c_str());
                    if (_AlloSize <= 0)
                    {
                        int ir19 = SendTcpData(_ClientSock, "500 Syntax error, command unrecognized\r\n");
                        if (ir19 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData 500 fail:ir19=%d\n", ir19);
                            _CanBeStopped = true;
                            break;
                        }
                    }
                    else
                    {
                        unsigned long long FreeSpace = 0;
                        if (GetMenuDiskFreeSpace(_RootDirectory.c_str(), FreeSpace) != 0)
                        {
                            _AlloSize = 0;
                            int ir20 = SendTcpData(_ClientSock, "451 Requested action aborted. Local error in processing\r\n");
                            if (ir20 != 0)
                            {
                                printf("FtpConnectingClient::ThreadFunc:SendTcpData 451 fail:ir20=%d\n", ir20);
                                _CanBeStopped = true;
                                break;
                            }
                        }
                        else
                        {
                            if (FreeSpace < (_AlloSize + 1024 * 1024 * 1024))
                            {
                                _AlloSize = 0;
                                int ir21 = SendTcpData(_ClientSock, "452 Requested action not taken.Insufficient storage space in system\r\n");
                                if (ir21 != 0)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:SendTcpData 452 fail:ir21=%d\n", ir21);
                                    _CanBeStopped = true;
                                    break;
                                }
                            }
                            else
                            {
                                int ir22 = SendTcpData(_ClientSock, "200 ALLO command successful.\r\n");
                                if (ir22 != 0)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:SendTcpData 200 fail:ir22=%d\n", ir22);
                                    _AlloSize = 0;
                                    _CanBeStopped = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                else if (StringFind(CBuf, "STOR") == true)
                {
                    int ir26 = SendTcpData(_ClientSock, "125 Data connection already open; Transfer starting.\r\n");
                    if (ir26 != 0)
                    {
                        printf("FtpConnectingClient::ThreadFunc:SendTcpData 125 fail:ir26=%d\n", ir26);
                        _CanBeStopped = true;
                        break;
                    }

                    fd_set fswStorAccept;
                    timeval tvwStorAccept = { 1, 0 };
                    int StorFdClient = -1;
                    unsigned int uiStorAcceptInx = 0;
                    while (_ThreadExit == false)
                    {
                        FD_ZERO(&fswStorAccept);
                        FD_SET(PasvFdServer, &fswStorAccept);
                        int sr2 = select(PasvFdServer + 1, &fswStorAccept, NULL, NULL, &tvwStorAccept);
                        if (sr2 < 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:select fail:sr2=%d\n", sr2);
                            _CanBeStopped = true;
                            break;
                        }
                        else if (sr2 > 0)
                        {
                            sockaddr_in saiStorFdClient;
                            int ilStorFdClient = sizeof(sockaddr_in);
                            StorFdClient = accept(PasvFdServer, (sockaddr *)&saiStorFdClient, &ilStorFdClient);
                            if (StorFdClient == -1)
                            {
                                printf("FtpConnectingClient::ThreadFunc:accept fail\n");
                                _CanBeStopped = true;
                            }
                            else
                            {
                                char StorClientIp[INET6_ADDRSTRLEN] = { 0 };
                                inet_ntop(AF_INET, (void *)&(saiStorFdClient.sin_addr), StorClientIp, sizeof(StorClientIp));
                                printf("FtpConnectingClient::ThreadFunc:ClientIp=%s,ClientPort=%hu,FdClient=%d\n", StorClientIp, saiStorFdClient.sin_port, StorFdClient);
                            }
                            break;
                        }
                        else
                        {
                            uiStorAcceptInx++;
                            if (uiStorAcceptInx >= 10)
                            {
                                printf("FtpConnectingClient::ThreadFunc:accept timeout\n");
                                _CanBeStopped = true;
                                break;
                            }
                        }
                    }
                    if (_ThreadExit == false)
                    {
                        if (_CanBeStopped == true)
                        {
                            int ir28 = SendTcpData(_ClientSock, "451 Requested action aborted. Local error in processing\r\n");
                            if (ir28 != 0)
                            {
                                printf("FtpConnectingClient::ThreadFunc:SendTcpData 451 fail:ir28=%d\n", ir28);
                            }
                            break;
                        }

                        std::string ssStorPath = "";
                        AnalyzeUserFromUserRequest(CBuf, ssStorPath);
                        ssStorPath = _RootDirectory + ssStorPath;
                        std::replace(ssStorPath.begin(), ssStorPath.end(), '\\', '/');
                        std::string ssStorMenu = ssStorPath.substr(0, ssStorPath.find_last_of('/'));
                        CreateMenu(ssStorMenu.c_str());
                        FILE *fwStor = fopen(ssStorPath.c_str(), _TransferMode == ascii ? "w" : "wb");
                        if (fwStor == nullptr)
                        {
                            int ir24 = SendTcpData(_ClientSock, "550 The system cannot find the path specified. \r\n");
                            if (ir24 != 0)
                            {
                                printf("FtpConnectingClient::ThreadFunc:SendTcpData 550 fail:ir24=%d\n", ir24);
                            }
                            closesocket(StorFdClient);
                            StorFdClient = -1;
                            _CanBeStopped = true;
                            break;
                        }

                        long lRecvStorSize = 0;
                        char c_buf_stor[1024] = { 0 };
                        while (_ThreadExit == false)
                        {
                            memset(c_buf_stor, 0, sizeof(c_buf_stor));
                            int RecvStorSize = 0;
                            int RecvCode = RecvTcpData(StorFdClient, c_buf_stor, sizeof(c_buf_stor), RecvStorSize);
                            if (RecvStorSize > 0)
                            {
                                if (fwrite(c_buf_stor, 1, RecvStorSize, fwStor) != RecvStorSize)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:fwrite fail\n");
                                    _CanBeStopped = true;
                                    break;
                                }
                            }
                            if (RecvCode < 0)
                            {
                                printf("FtpConnectingClient::ThreadFunc:RecvTcpData fail:RecvCode=%d\n", RecvCode);
                                _CanBeStopped = true;
                                break;
                            }
                            else if (RecvCode == 1)
                            {
                                if (_AlloSize > 0)
                                {
                                    if (lRecvStorSize != _AlloSize)
                                    {
                                        printf("FtpConnectingClient::ThreadFunc:RecvTcpData fail:RecvCode=%d\n", RecvCode);
                                        _CanBeStopped = true;
                                    }
                                }
                                break;
                            }

                            lRecvStorSize += RecvStorSize;
                            if (_AlloSize > 0)
                            {
                                if (lRecvStorSize == _AlloSize)
                                {
                                    break;
                                }
                                else if (lRecvStorSize > _AlloSize)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:recv len error\n");
                                    _CanBeStopped = true;
                                    break;
                                }
                            }
                            std::this_thread::sleep_for(std::chrono::microseconds(1));
                        }
                        fclose(fwStor);
                        fwStor = nullptr;
                        closesocket(StorFdClient);
                        StorFdClient = -1;
                        if (_ThreadExit == false)
                        {
                            if (_CanBeStopped == true)
                            {
                                remove(ssStorPath.c_str());
                                int ir29 = SendTcpData(_ClientSock, "451 Requested action aborted. Local error in processing\r\n");
                                if (ir29 != 0)
                                {
                                    printf("FtpConnectingClient::ThreadFunc:SendTcpData 451 fail:ir29=%d\n", ir29);
                                }
                                break;
                            }

                            int ir25 = SendTcpData(_ClientSock, "226 Transfer complete.\r\n");
                            if (ir25 != 0)
                            {
                                printf("FtpConnectingClient::ThreadFunc:SendTcpData 226 fail:ir25=%d\n", ir25);
                                _CanBeStopped = true;
                                break;
                            }
                        }
                        else
                        {
                            int ir33 = SendTcpData(_ClientSock, "451 Requested action aborted. Local error in processing\r\n");
                            if (ir33 != 0)
                            {
                                printf("FtpConnectingClient::ThreadFunc:SendTcpData 451 fail:ir33=%d\n", ir33);
                            }
                        }
                    }
                    else
                    {
                        if (StorFdClient != -1)
                        {
                            closesocket(StorFdClient);
                            StorFdClient = -1;
                        }
                        int ir32 = SendTcpData(_ClientSock, "451 Requested action aborted. Local error in processing\r\n");
                        if (ir32 != 0)
                        {
                            printf("FtpConnectingClient::ThreadFunc:SendTcpData 451 fail:ir32=%d\n", ir32);
                        }
                    }
                }
                else
                {
                    int ir14 = SendTcpData(_ClientSock, "500 Syntax error, command unrecognized\r\n");
                    if (ir14 != 0)
                    {
                        printf("FtpConnectingClient::ThreadFunc:SendTcpData 500 fail:ir14=%d\n", ir14);
                    }
                    _CanBeStopped = true;
                    break;
                }
            }
        }
    }
    if (PasvFdServer != -1)
    {
        closesocket(PasvFdServer);
        PasvFdServer = -1;
    }
    printf("FtpConnectingClient::ThreadFunc:thread %d end\n", std::this_thread::get_id());
}


#ifndef FTPSERVER_H
#define FTPSERVER_H

#include <thread>

/** ftp服务端 */
class FtpServer
{
public:
    FtpServer();
    ~FtpServer();

    /** 开启:RootDirectory-根目录,ControlPort-控制端口,MaxClientCnt-最大客户端数量:返回0-成功,-1-初始化套接字库失败,-2-创建线程失败 */
    int start(const char *RootDirectory, unsigned short ControlPort = 21, int MaxClientCnt = 10);
    /** 停止 */
    void stop();

private:
    /** 根目录 */
    std::string m_RootDirectory;
    /** 控制端口 */
    unsigned short m_ControlPort;
    /** 最大客户端数量 */
    int m_MaxClientCnt;
    /** 线程退出标识 */
    bool m_ThreadExit;
    /** 线程 */
    std::thread m_thread;

    /** 线程函数 */
    void ThreadFunc();
};

#endif


#include "FtpServer.h"
#include <WinSock2.h>
#include <vector>
#include "FtpConnectingClient.h"
#include <algorithm>
#include <WS2tcpip.h>
#include "TcpCommon.h"

#pragma comment(lib, "Ws2_32.lib")

FtpServer::FtpServer()
{
    m_RootDirectory = "";
    m_ControlPort = 0;
    m_MaxClientCnt = 0;
    m_ThreadExit = true;
}

FtpServer::~FtpServer()
{
    stop();
}

int FtpServer::start(const char *RootDirectory, unsigned short ControlPort, int MaxClientCnt)
{
    printf("FtpServer::start:RootDirectory=%s,ControlPort=%hu,MaxClientCnt=%d\n", RootDirectory, ControlPort, MaxClientCnt);
    WSADATA _wsa;
    if (WSAStartup(MAKEWORD(2, 2), &_wsa) != 0)
    {
        return -1;
    }

    m_RootDirectory = RootDirectory;
    std::replace(m_RootDirectory.begin(), m_RootDirectory.end(), '\\', '/');
    if (m_RootDirectory.at(m_RootDirectory.length() - 1) == '/')
    {
        m_RootDirectory = m_RootDirectory.substr(0, m_RootDirectory.length() - 1);
    }
    printf("FtpServer::start:m_RootDirectory=%s\n", m_RootDirectory.c_str());
    m_ControlPort = ControlPort;
    m_MaxClientCnt = MaxClientCnt;
    m_ThreadExit = false;
    m_thread = std::thread(&FtpServer::ThreadFunc, this);
    if (m_thread.joinable() == false)
    {
        m_ThreadExit = true;
        WSACleanup();
        return -2;
    }

    return 0;
}

void FtpServer::stop()
{
    m_ThreadExit = true;
    if (m_thread.joinable() == true)
    {
        m_thread.join();
    }
    WSACleanup();
}

void FtpServer::ThreadFunc()
{
    printf("FtpServer::ThreadFunc:thread %d begin\n", std::this_thread::get_id());
    int FdServerControl = CreateTcpServer(m_ControlPort, m_MaxClientCnt);
    if (FdServerControl != -1)
    {
        printf("FtpServer::ThreadFunc:CreateTcpServer success:FdServerControl=%d\n", FdServerControl);
    }
    else
    {
        printf("FtpServer::ThreadFunc:CreateTcpServer fail\n");
    }
    fd_set fs;
    timeval tv = { 1, 0 };
    std::vector<FtpConnectingClient *> svcc;
    while (m_ThreadExit == false)
    {
        if (FdServerControl == -1)
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            FdServerControl = CreateTcpServer(m_ControlPort, m_MaxClientCnt);
            if (FdServerControl != -1)
            {
                printf("FtpServer::ThreadFunc:CreateTcpServer success:FdServerControl=%d\n", FdServerControl);
            }
            else
            {
                printf("FtpServer::ThreadFunc:CreateTcpServer fail\n");
            }
            continue;
        }

        for (std::vector<FtpConnectingClient *>::iterator it = svcc.begin(); it != svcc.end(); it++)
        {
            FtpConnectingClient *cc = *it;
            if (cc->GetCanBeStopped() == true)
            {
                svcc.erase(it);
                delete cc;
                cc = nullptr;
                break;
            }
        }

        FD_ZERO(&fs);
        FD_SET(FdServerControl, &fs);
        int sr = select(FdServerControl + 1, &fs, NULL, NULL, &tv);
        if (sr < 0)
        {
            printf("FtpServer::ThreadFunc:select fail\n");
            while (svcc.size() > 0)
            {
                FtpConnectingClient *cc = svcc.front();
                svcc.erase(svcc.begin());
                delete cc;
                cc = nullptr;
            }
            closesocket(FdServerControl);
            FdServerControl = -1;
        }
        else if (sr > 0)
        {
            sockaddr_in client_address;
            int address_len = sizeof(sockaddr_in);
            int FdClientControl = accept(FdServerControl, (sockaddr *)&client_address, &address_len);
            if (FdClientControl != -1)
            {
                if (svcc.size() >= m_MaxClientCnt)
                {
                    printf("FtpServer::ThreadFunc:the link has reached the limit\n");
                    closesocket(FdClientControl);
                }
                else
                {
                    char LocalIp[INET6_ADDRSTRLEN] = { 0 };
                    sockaddr sa = { 0 };
                    int sal = sizeof(sockaddr);
                    if (getsockname(FdClientControl, &sa, &sal) != 0)
                    {
                        printf("FtpServer::ThreadFunc:get local ip fail\n");
                        closesocket(FdClientControl);
                    }
                    else
                    {
                        inet_ntop(AF_INET, (void *)&((sockaddr_in *)&sa)->sin_addr, LocalIp, sizeof(LocalIp));
                        printf("FtpServer::ThreadFunc:LocalIp=%s\n", LocalIp);
                        char ClientIp[INET6_ADDRSTRLEN] = { 0 };
                        inet_ntop(AF_INET, (void *)&(client_address.sin_addr), ClientIp, sizeof(ClientIp));
                        printf("FtpServer::ThreadFunc:ClientIp=%s,ClientPort=%hu\n", ClientIp, client_address.sin_port);
                        FtpConnectingClient *cc = new FtpConnectingClient();
                        if (cc->start(FdClientControl, m_RootDirectory, LocalIp) != 0)
                        {
                            printf("FtpServer::ThreadFunc:cc->start fail\n");
                            delete cc;
                            cc = nullptr;
                        }
                        else
                        {
                            svcc.push_back(cc);
                        }
                    }
                }
            }
            else
            {
                printf("FtpServer::ThreadFunc:accept fail\n");
            }
        }
    }
    if (FdServerControl != -1)
    {
        while (svcc.size() > 0)
        {
            FtpConnectingClient *cc = svcc.front();
            svcc.erase(svcc.begin());
            delete cc;
            cc = nullptr;
        }
        closesocket(FdServerControl);
    }
    printf("FtpServer::ThreadFunc:thread %d end\n", std::this_thread::get_id());
}


#include "FtpServer.h"

int main()
{
    FtpServer fs;
    fs.start("E:\\ft_server_test\\", 3001, 1);
    getchar();
    fs.stop();
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux C FTP是一种在Linux操作系统下使用C语言开发的FTP(File Transfer Protocol,文件传输协议)客户端程序。它可以通过FTP协议在网络上进行文件的上传和下载。 Linux C FTP的实现主要涉及以下几个方面:socket编程、命令解析和响应处理、文件传输。 首先,Linux C FTP利用socket编程来建立与FTP服务器的连接,通过socket套接字进行数据的传输和通信。 其次,命令解析和响应处理是FTP客户端程序的关键。用户可以通过输入指令来进行各种操作,如登录、查看文件列表、上传和下载文件等。Linux C FTP通过解析用户的输入指令,并根据指令向FTP服务器发送请求。同时,它还能够接收FTP服务器返回的响应信息,并进行相应的处理和显示。 最后,文件传输是Linux C FTP的核心功能之一。通过FTP协议,可以实现文件在客户端和服务器之间的相互传输。用户可以选择上传文件到服务器或从服务器下载文件到本地。在文件传输过程中,Linux C FTP需要处理数据的分块、校验和传输中断等问题,以保证文件的完整性和可靠性。 总结来说,Linux C FTP是一种基于Linux操作系统的FTP客户端程序,通过socket编程实现与FTP服务器的连接和通信,通过命令解析和响应处理实现用户指令的解析和处理,通过文件传输实现文件的上传和下载。它为用户提供了方便快捷的文件传输功能,是网络上传输文件的重要工具之一。 ### 回答2: Linux C FTP是指在Linux系统下使用C语言编写的FTP(File Transfer Protocol,文件传输协议)客户端。FTP是一种用于在网络上传输文件的协议,它允许用户通过客户端与远程服务器进行文件的上传、下载和管理。 使用C语言编写Linux FTP客户端,可以通过套接字(Socket)来实现与服务器的通信。通过建立与远程服务器的连接,并发送相应的FTP命令来实现文件传输功能。 首先,客户端需要通过socket函数创建一个套接字,并指定远程服务器的IP地址和FTP服务器的端口号。然后,使用connect函数将套接字连接到服务器。 连接建立后,客户端可以使用send函数向服务器发送FTP命令,例如发送"USER"命令进行登录验证,发送"PASS"命令输入登录密码。利用recv函数接收服务器返回的响应信息,判断登录是否成功。 登录成功后,客户端可以发送"RETR"命令下载文件,指定要下载的文件名和保存的本地路径;发送"STOR"命令上传文件,指定要上传的本地文件名和服务器保存的路径。客户端还可以发送"LIST"命令获取服务器上的文件列表。 发送完FTP命令后,客户端通过recv函数接收服务器返回的响应信息,根据返回的响应状态码进行相应的处理。例如,状态码为"150"表示服务器准备传输文件,客户端可以通过recv函数接收数据并将数据写入指定的本地文件。 当文件传输结束后,客户端可以使用"QUIT"命令关闭连接并退出。 以上是简单介绍了使用Linux C语言编写FTP客户端的基本步骤。在实际应用中,还需要处理其他一些细节,比如错误处理、断点续传等,以提高文件传输的可靠性和效率。 ### 回答3: Linux C FTP是指在Linux系统下使用C语言编写的FTP客户端程序。FTP全称为File Transfer Protocol,是一种用于在网络上进行文件传输的标准协议。利用FTP,用户可以通过一个客户端程序连接到FTP服务器,进行上传和下载文件的操作。 Linux C FTP程序的编写需要使用C语言和Linux系统提供的相关库函数。首先,需要建立一个与FTP服务器的连接,可以使用socket函数创建一个套接字,并使用connect函数将套接字连接到服务器的IP地址和端口号。连接建立后,客户端需要与服务器进行握手和认证,通常通过用户输入用户名和密码进行身份验证。 在认证成功后,客户端可以发送FTP命令到服务器,包括获取文件列表、上传文件、下载文件等操作。这些FTP命令通过客户端发送给服务器进行处理。常用的FTP命令包括: - LIST:获取服务器上的文件列表 - RETR:从服务器下载文件 - STOR:上传文件到服务器 - DELE:删除服务器上的文件 - MKD:创建目录 - CWD:切换目录 - PWD:获取当前所在目录 客户端程序需要根据用户的操作,在C语言中编写相应的函数来执行对应的FTP命令。例如,下载文件可以使用recv函数接收服务器发来的文件数据,并使用write函数将数据写入到本地文件;上传文件则需要使用send函数将文件数据发送给服务器。 编写Linux C FTP程序,需要熟悉Linux系统的网络编程和FTP协议的相关知识。同时,还需要考虑到网络传输的安全性和稳定性等因素,例如可以使用SSL/TLS来加密数据传输,以及进行错误处理和异常处理,以提高程序的健壮性。 总之,Linux C FTP是一种在Linux系统下使用C语言编写的FTP客户端程序,通过与FTP服务器进行交互,实现文件的传输和管理。编写这样的程序需要了解Linux系统的网络编程和FTP协议的相关知识,并综合考虑程序的安全性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值