linux c 实现简单版 ftp 服务器

ftp协议简单的介绍下  ftp 传输分为命令传输 (命令都是字符串) 和数据传输  它们各使用一个独立socket通信
当服务端接收到客户端的 命令后 解析 如果命令是上传或下载文件 则服务端打开一个新的socket 并监听 同时把自己监听的ip 端口通过命令socket 发给客户端 客户端接收到后
 新建一个socket 去链接这个ip 端口链接到 服务端的数据socket 接收或发送数据  
注意命令socket一直是保持链接的 数据socket 另外开
还有就是 ftp协议的数据传输分为主动和被动两种模式  其区别就是 一个是由服务端打开数据socket等待客户端来链接 另一个是 客户端打开socket 等待服务端来链接

具体的流程可以参看filezilla 这个软件 输出的命令交互信息


//ftpserver.h
//-------------------------
#ifndef __FTPSERVER_H__
#define __FTPSERVER_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
struct data {
    char ip[100];
    short port;
    char user[100];
    char pass[100];
    char url[100];
    int sock;
    pthread_t pid;
    FILE *fp;
};

void server_init(struct data *data);
void server_set(struct data *data, const char *addr, short port, const char *user, const char *pass, const char *rooturl);
int server_start(struct data *data);
void server_stop(struct data *data);

#ifdef __cplusplus
}
#endif
#endif // __FTPSERVER_H__




//ftpserver.c

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/wait.h>
#include "ftpserver.h"
#ifdef __cplusplus
extern "C" {
#endif

struct ftp_server {
    int ofs;
    int port_ip;
    short port_port;
    int c_sock;
    int d_sock;
    int data_sock;
    int c_addr;
    short c_port;
    int d_addr;
    short d_port;
    int islogin;
    char rename[256];
    char send_buf[256];
    char user[100];
    char pass[100];
    void *data;
};

static pid_t pid_arr[256];

static void sig_fun(int sig)
{
    int status, i;
    pid_t pid = wait(&status);
    for (i = 0; i < sizeof(pid_arr) / sizeof(pid_arr[0]); i++) {
        if (pid_arr[i] == pid) {
            pid_arr[i] = 0;
        }
    }
}

static void close_tenor(void)
{
    int i;
    for (i = 0; i < sizeof(pid_arr) / sizeof(pid_arr[0]); i++) {
        if (pid_arr[i]) {
            kill(pid_arr[i], SIGINT);
            pid_arr[i] = 0;
        }
    }
}

static char *my_split(char *src, const char *key, int *len, char **data)
{
    char *pos, *p;
    if (src) *data = src;
    pos = strstr(*data, key);
    if (!pos) {
        *len = 0;
        return *data;
    } else {
        *len = pos - *data;
        p = *data;
        while (!memcmp(pos, key, strlen(key))) {
            pos += strlen(key);
        }
        *data = pos;
        return p;
    }
}



static int ftp_server_user(struct ftp_server *server, const char *cmd)
{
    char *start;
    start = strstr(cmd, " ");
    if (!start) return -1;
    start++;
    if (!strcmp(server->user, start)) {
        sprintf(server->send_buf, "331 Password required\r\n");
        server->islogin = 1;
    } else {
        sprintf(server->send_buf, "332 notfound user\r\n");
        server->islogin = 0;
    }
    printf("%s", server->send_buf);
    send(server->c_sock, server->send_buf, strlen(server->send_buf), 0);
    return 0;
}

static int ftp_server_pass(struct ftp_server *server, const char *cmd)
{
    char *start;
    start = strstr(cmd, " ");
    if (!start) return -1;
    start++;

    if (!strcmp(server->pass, start)) {
        sprintf(server->send_buf, "230 User logged in..\r\n");
        if (server->islogin == 1)
            server->islogin = 2;
        else
            server->islogin = 0;
    } else {
        sprintf(server->send_buf, "331 Need password login\r\n");
        server->islogin = 0;
    }

    printf("%s", server->send_buf);
    send(server->c_sock, server->send_buf, strlen(server->send_buf), 0);
    return 0;
}

static int ftp_server_syst(struct ftp_server *server, const char *cmd)
{
    printf("%s", "215 UNIX emulated by FileZilla\r\n");
    send(server->c_sock, "215 UNIX emulated by FileZilla\r\n", strlen("215  UNIX emulated by FileZilla\r\n"), 0);
    return 0;
}

static int ftp_server_pwd(struct ftp_server *server, const char *cmd)
{
    char buf[128] = {};
    getcwd(buf, sizeof(buf) - 1);
    sprintf(server->send_buf, "257 \"%s\" is current directory.\r\n", buf);
    printf("%s", server->send_buf);
    send(server->c_sock, server->send_buf, strlen(server->send_buf), 0);
    return 0;
}

static int ftp_server_type(struct ftp_server *server, const char *cmd)
{
    char *start;
    start = strstr(cmd, " ");
    if (!start) return -1;
    start++;
    if (!strncmp(start, "I", 1)) {
        sprintf(server->send_buf, "200 Type set to I.\r\n");
    } else {
        sprintf(server->send_buf, "500 : command not understood.\r\n");
    }
    printf("%s", server->send_buf);
    send(server->c_sock, server->send_buf, strlen(server->send_buf), 0);
    return 0;
}

static int ftp_server_pasv(struct ftp_server *server, const char *cmd)
{
    int ret;
    struct sockaddr_in addr;

    server->port_ip = 0;
    server->d_sock = socket(AF_INET, SOCK_STREAM , 0);
    if (server->d_sock == -1) {
        return -1;
    }
    struct timeval timeout = {6, 0};
    setsockopt(server->d_sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
    //设置接收超时
    setsockopt(server->d_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));

    addr.sin_addr.s_addr = server->d_addr;
    addr.sin_port = 0;
    addr.sin_family = AF_INET;

    int opt=SO_REUSEADDR;
    setsockopt(server->d_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    ret = bind(server->d_sock, (struct sockaddr *)&addr, sizeof(addr));
    if (ret != 0) {
        return -1;
    }

    struct sockaddr_in localaddr;
    socklen_t locallen = sizeof(local
  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值