ftp服务器的简单实现——服务器端

Posted 众生皆苦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ftp服务器的简单实现——服务器端相关的知识,希望对你有一定的参考价值。

服务器端的代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#define TRUE 1
#define LISTEN_PORT 3499
#define dataLen 1024

char currentDirPath[200];
char currentDirName[30];
char help[]={"get   get a file from server\n"    
            "put upload a file to server\n"
            "pwd display the current directory of server\n"
            "cd change the directory of server\n"
            "?   display the whole command which equals ‘help‘\n"
            "quit   return \n"};

char *getDirName(char *dirPathName);
void cmd_pwd(int sock);
void cmd_dir(int sock);
void cmd_cd(int sock, char *dirName);
void cmd_cdback(int sock);
void cmd_help(int sock);
void cmd_get(int sock, char *fileName);
void cmd_put(int sock, char *fileName);

int main(int argc, char *argv[])
{
    int sock, sockmsg, length, lengthmsg;
    char client_cmd[10], cmd_arg[20];
    struct sockaddr_in server;
    struct sockaddr_in servermsg;
    int datasock, msgsock;
    pid_t child;

    //int datasock;  //data socket
    int rval;
    sock = socket(AF_INET, SOCK_STREAM, 0);
    sockmsg = socket(AF_INET, SOCK_STREAM, 0);

    if(sock < 0 || sockmsg < 0)
    {
        perror("opeing stream socket");
        exit(0);
    }

    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(LISTEN_PORT);
    
    servermsg.sin_family = AF_INET;
    servermsg.sin_addr.s_addr = INADDR_ANY;
    servermsg.sin_port = htons(LISTEN_PORT+1);
    
  
    if(bind(sock, (struct sockaddr *)&server, sizeof(server)) <0 
       || bind(sockmsg, (struct sockaddr*)&servermsg, sizeof(servermsg))<0 )
    {
        perror("binding stream socket");
        exit(1);
    }

    length = sizeof(server);
    lengthmsg = sizeof(servermsg);
    if(getsockname(sock, (struct sockaddr *)&server, &length) < 0 ||
        getsockname(sockmsg, (struct sockaddr *)&servermsg, &lengthmsg) < 0)
    {
        perror("getting socket name");
        exit(1);
    }    

    printf("Socket port # %d %d\n", ntohs(server.sin_port), ntohs(servermsg. sin_port));
    memset(currentDirPath, 0, sizeof(currentDirPath));
    getcwd(currentDirPath, sizeof(currentDirPath));

    listen(sock, 2);
    listen(sockmsg, 2);
    do
    {
        datasock = accept(sock, (struct sockaddr *)0, (int *)0);
        msgsock = accept(sockmsg, (struct sockaddr*)0, (int *)0);
        if(-1 == datasock || -1 == msgsock)
        {
            perror("accept");
        }
        else
        {
            if(-1 == (child = fork()))
            {
                printf("Fork Error!\n");
            }
            //The child process
            if(0 == child)
            {
                printf("connection accepted! new client comming\n");
loop:
                memset(client_cmd, 0, sizeof(client_cmd));
                rval = 0;
                rval = read(msgsock, client_cmd, sizeof(client_cmd));
                
                if(rval < 0)
                {
                    perror("reading command failed\n");
                }
                else if(0 == rval)
                {
                    printf("connection closed.\n");
                    close(datasock);
                    close(msgsock);
                }
                else
                {
                    if(strcmp(client_cmd, "pwd") == 0)
                    {
                        printf("command pwd\n");
                        cmd_pwd(datasock);
                        printf("done\n\n");
                        goto loop;
                    }
                    else if(strcmp(client_cmd, "dir") == 0)
                    {
                        printf("command dir\n");
                        cmd_dir(datasock);
                        printf("\n\n");
                        goto loop;
                    }
                    else if(strcmp(client_cmd, "cd") == 0)
                    {
                        printf("command cd\n");
                        memset(cmd_arg, 0, sizeof(cmd_arg));
                        read(msgsock, cmd_arg, sizeof(cmd_arg));
                        cmd_cd(datasock, cmd_arg);
                        printf("done\n\n");
                        goto loop;
                    }
                    else if(strcmp(client_cmd, "cd..") == 0)
                    {
                        printf("command cd..\n");
                        cmd_cdback(datasock);
                        printf("done\n\n");
                        goto loop;
                    }
                    
                    else if(strcmp(client_cmd, "get") == 0)
                    {
                        printf("command get\n");
                        memset(cmd_arg, 0, sizeof(cmd_arg));
                        read(msgsock, cmd_arg, sizeof(cmd_arg));
                        cmd_get(datasock, cmd_arg);
                        printf("done\n\n");
                        goto loop;
                    }
                    else if(strcmp(client_cmd, "put") == 0)
                    {
                        printf("command get\n");
                        memset(cmd_arg, 0, sizeof(cmd_arg));
                        read(msgsock, cmd_arg, sizeof(cmd_arg));
                        cmd_put(datasock, cmd_arg);
                        printf("done\n\n");
                        goto loop;
                    }
                    else if(strcmp(client_cmd, "?") == 0)
                    {
                        printf("command ?\n");
                        cmd_help(datasock);
                        printf("done\n\n");
                        goto loop;
                    }
                    else if(strcmp(client_cmd, "quit") == 0)
                    {
                        printf("quit\n");
                        goto endchild;
                    }
                    else
                    {
                        printf("bad request\n");
                        goto loop;
                    }
                }
endchild:
                printf("connection closed.\n");
                close(datasock);
                close(msgsock);
                exit(0);
            }

        }
    }while(TRUE);

    exit(0);
}

//pwd command
void cmd_pwd(int sock)
{
    int len;
    memset(currentDirPath, 0, sizeof(currentDirPath));
    getcwd(currentDirPath, sizeof(currentDirPath));
    char *savePointer = getDirName(currentDirPath);
    printf("currentDirPath is %s", currentDirPath);
    strcpy(currentDirName, savePointer);

    printf("currentDirName is %s\n", currentDirName);
    len = strlen(currentDirName)+1;
    printf("len is %d\n", len);
    write(sock, currentDirName, len);
}

//dir command
void cmd_dir(int sock)
{
    DIR *pdir;
    char fileName[30];
    char fileInfo[50];
    int i, fcounts = 0, len;
    struct dirent *pent;
    int fd;
    struct stat fileSta;
    char filePath[200];

    pdir = opendir(currentDirPath);
    pent = readdir(pdir);

    while(pent!=NULL)
    {
        fcounts++;
        pent = readdir(pdir);
    }

    write(sock, &fcounts, sizeof(int));
    closedir(pdir);
    
    if(fcounts <= 0)
    {
        return;
    }
    else
    {
        pdir = opendir(currentDirPath);
        for(i=0; i<fcounts; i++)
        {
            pent = readdir(pdir);
            memset(fileName, 0, 30);
            memset(fileInfo, 0, sizeof(fileInfo));
            strcpy(fileName, pent->d_name);
            
            //check the file is a directory or a file
            memset(filePath, 0, sizeof(filePath));
            strcpy(filePath, currentDirPath);
            strcat(filePath, "/");
            strcat(filePath, fileName);
            fd = open(filePath, O_RDONLY, S_IREAD);
            
            fstat(fd, &fileSta);
            if(S_ISDIR(fileSta.st_mode))
            {
                strcat(fileInfo, "dir\t");
                strcat(fileInfo, fileName);
            }
            else
            {
                strcat(fileInfo, "file\t");
                strcat(fileInfo, fileName);
            }
            write(sock, fileInfo, sizeof(fileInfo));
        }
        closedir(pdir);
    }
}

void cmd_cd(int sock, char *dirName)
{
    DIR *pdir;
    struct dirent *pent;
    char filename[30];
    int i,fcounts = 0;
    int flag = 0;

    pdir = opendir(currentDirPath);
    pent = readdir(pdir);
    
    printf("currentDirPath is %s\n", currentDirPath);
    while(pent != NULL)
    {
        fcounts++;
        pent = readdir(pdir);
    }

    closedir(pdir);
    if(fcounts <= 0)
    {
        return;
    }
    else
    {
        pdir = opendir(currentDirPath);
        for(i=0; i<fcounts; i++)
        {
            pent = readdir(pdir);
            if(strcmp(pent->d_name, dirName) == 0)
            {
                strcat(currentDirPath, "/");
                strcat(currentDirPath, dirName);
                flag = 1;
                break;
            }
        }

        if(flag == 1)
        {
            write(sock, currentDirPath, sizeof(currentDirPath));
        }
        closedir(pdir);
    }
}

//command cd..
void cmd_cdback(int sock)
{
    int len;
    int i, record;
    
    len = strlen(currentDirPath);

    for(i=len-1; i>=0; i--)
    {
        if(currentDirPath[i] == /)
        {
            currentDirPath[i] = \0;
            break;
        }
        currentDirPath[i] = \0;
    }
}

//command ?
void cmd_help(int sock)
{
    int len = strlen(help)+1;
    write(sock, help, len);
}

//command get
void cmd_get(int sock, char* fileName)
{
    int fd;
    struct stat fileSta;
    long fileSize;
    char filePath[200], buf[dataLen];
    
    memset(filePath, 0, sizeof(filePath));
    strcpy(filePath, currentDirPath);
    strcat(filePath, "/");
    strcat(filePath, fileName);

    fd = open(filePath, O_RDONLY, S_IREAD);
    if(fd != -1)
    {
        fstat(fd, &fileSta);
        fileSize = (long)fileSta.st_size;
        write(sock, &fileSize, sizeof(long));
        memset(buf, 0, dataLen);
        while(fileSize > dataLen)
        {
            read(fd, buf, dataLen);
            write(sock, buf, dataLen);
            fileSize = fileSize - dataLen;
        }

        read(fd, buf, fileSize);
        write(sock, buf, fileSize);
        close(fd);
        printf("transfer completed\n");
    }
    else
    {
        printf("open file %s failed\n", filePath);
    }
}

//command put
void cmd_put(int sock, char *fileName)
{
    int fd;
    long fileSize;
    
    char filePath[200], buf[dataLen];
    strcpy(filePath, currentDirPath);
    strcat(filePath, "/");
    strcat(filePath, fileName);

    fd = open(filePath, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
    if(fd != -1)
    {
        memset(buf, 0, dataLen);
        read(sock, &fileSize, sizeof(long));

        while(fileSize > dataLen)
        {
            read(sock, buf, dataLen);
            write(fd, buf, dataLen);
            fileSize = fileSize - dataLen;
        }

        read(sock, buf, fileSize);    
        write(fd, buf, fileSize);

        close(fd);
        printf("transfer completed\n");
    }
    else
    {
        printf("open file %s failed\n", filePath);
    }
}

//get the last string afer the last cha ‘/‘
char *getDirName(char *dirPathName)
{
    int i, pos, len;
    char *dirName;

    if(dirPathName == NULL)
    {
        printf("directory absoultly path is null\n");
        return NULL;
    }

    len = strlen(dirPathName);
    for(i=len-1; i>=0; i--)
    {
        if(dirPathName[i] == /)
        {
            pos = i;
            break;
        }
    }

    dirName = (char *)malloc(len-pos+1);
    for(i=pos+1; i<len; i++)
    {
        printf("%c",dirPathName[i]);
        dirName[i-pos-1] = dirPathName[i];
    }

    return dirName;
}

用gcc -o server server.c

如果加上调试信息就是gcc -g -o server server.c

以上是关于ftp服务器的简单实现——服务器端的主要内容,如果未能解决你的问题,请参考以下文章

简单的单进程FTP服务器的实现

在vs code中使用ftp-sync插件实现客户端与服务器端代码的同步

在vs code中使用ftp-sync插件实现客户端与服务器端代码的同步

python实现FTP服务器

socket实现的简单的ftp服务

实现简单socket的ftp功能