自己实现一个简单的ftp软件

来源:互联网 发布:软件项目沟通机制 编辑:程序博客网 时间:2024/06/07 12:21

近期面试有个机试题是写个ftp软件,自己写完不想就扔了,就放到这里大家参考一下,也帮我优化优化,没什么太难的也就不需要什么注释了

消息格式:

cmd | size | data

服务端:

#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <arpa/inet.h>#include <netinet/in.h>#include <dirent.h>#include <stdlib.h>#define COMPARE(a, b, c) (strcmp(a, c) b 0) #define HEAD_SIZE 4char *packet(int size, const char *data);int main(int argc, const char *argv[]){    int sockfd, acceptfd;    struct sockaddr_in myaddr;    memset(&myaddr, 0, sizeof(myaddr));    socklen_t addrlen = sizeof(struct sockaddr_in);    sockfd = socket(AF_INET, SOCK_STREAM, 0);    if (sockfd == -1) return -1;     myaddr.sin_family = AF_INET;    myaddr.sin_port = htons(6060);    myaddr.sin_addr.s_addr = inet_addr("192.168.255.128");    int optval = 1;    socklen_t optlen = sizeof(optval);    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen); //设置端口重用    if (bind(sockfd, (struct sockaddr *)&myaddr, addrlen) == -1) {        printf("bind faild\n");        return -1;    }    if (listen(sockfd, 10) == -1) {        printf("listen faild\n");        return -1;    }    if ((acceptfd=accept(sockfd, (struct sockaddr *)&myaddr, &addrlen)) == -1) {        printf("acceptfd faild\n");        return -1;    }    ssize_t recvlen, sendlen;    char buf[256];    DIR *dirfd;    while (1) { //注意服务端使用的消息格式是size|data        recv(acceptfd, buf, 4, 0); //先接收开始的四个字节cmd        if (COMPARE(buf, ==, "get")) {            memset(buf, 0, 0);            recv(acceptfd, buf, 4, 0);            int size = *(int *)buf;            recv(acceptfd, buf, size, 0);            printf("%s\n", buf);            FILE *fp = fopen(buf, "rb");            if (fp == NULL) {                printf("file open failed\n");                break;            }            memset(buf,  0, 0); //使用buf前先清空一下,防止出现其它不想要的字符            size_t readlen = fread(buf, 1, sizeof(buf), fp);            char *tmp = packet(readlen, buf);            send(acceptfd, tmp, HEAD_SIZE+readlen, 0);            free(tmp);            fclose(fp);        } else if (COMPARE(buf, ==, "ls")) {            printf("%s\n", buf);            if ((dirfd = opendir("./")) == NULL) {                char *tmp = packet(8, "no file");                send(sockfd, tmp, HEAD_SIZE + 8, 0);                free(tmp);                printf("file open failed\n");            } else {                struct dirent *pdirent;                while ((pdirent = readdir(dirfd)) != NULL) {                    if (pdirent->d_name[0] == '.')                        continue;                    char *tmp = packet(strlen(pdirent->d_name)+1, pdirent->d_name);                    sendlen = send(acceptfd, tmp, HEAD_SIZE + strlen(pdirent->d_name)+1, 0);                    if (sendlen == 0) break;                    free(tmp);                }                char *tmp = packet(4, "ok");                send(acceptfd, tmp, HEAD_SIZE + 3, 0);            }        } else if (COMPARE(buf, ==, "put")) {            printf("%s\n", buf);            recv(acceptfd, buf, 4, 0);            int size = *(int *)buf;            memset(buf, 0, 0);            size_t recvlen = recv(acceptfd, buf, size, 0);            FILE *fp = fopen("./update.txt", "wb");            if (fp == NULL) {                printf("file open failed\n");                break;            }            fwrite(buf, 1, recvlen, fp);            strcpy(buf, "ok");            send(acceptfd, buf, 3, 0);            fclose(fp);        }    }    close(sockfd);    close(acceptfd);    return 0;}char *packet(int size, const char *data) {    char *ret = malloc(sizeof(int) + size);    *(int *)ret = size;    memcpy(ret + HEAD_SIZE, data, size);    return ret;}

客户端:

#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <arpa/inet.h>#include <netinet/in.h>#include <stdlib.h>#define COMPARE(a, b, c) (strcmp(a, c) b 0)#define HEAD_SIZE 8char *packet(const char *cmd, int size, const char *data);int main(int argc, const char *argv[]){    int sockfd;    struct sockaddr_in myaddr;    memset(&myaddr, 0, sizeof(myaddr));    socklen_t addrlen = sizeof(struct sockaddr_in);    sockfd = socket(AF_INET, SOCK_STREAM, 0);    if (sockfd == -1) return -1;     myaddr.sin_family = AF_INET;    myaddr.sin_port = htons(6060);    myaddr.sin_addr.s_addr = inet_addr("192.168.255.128");    if (connect(sockfd, (struct sockaddr *)&myaddr, addrlen) == -1) {        printf("connect faild\n");        return -1;    }    ssize_t recvlen, sendlen;    char buff[256];    char send_buff[256];    char recv_buff[256];    char *token = NULL;    char *delim = " ";    while (1) {        printf("ftp > ");        fgets(buff, sizeof(buff), stdin);        buff[strlen(buff) - 1] = 0;        char *tmp = buff;        if (*tmp == 0) continue;        token = strtok(tmp, delim);#if 1        if (COMPARE(token, ==, "ls")) {            char *send_data = packet("ls", 0, NULL);            send(sockfd, send_data, HEAD_SIZE, 0);            free(send_data);            while (1) {                recvlen = recv(sockfd, recv_buff, 4, 0);                if (recvlen <= 0) break;                int size = *(int *)recv_buff;                memset(recv_buff, 0, 0);                recv(sockfd, recv_buff, size, 0);                if (COMPARE(recv_buff, ==, "ok")) break;                printf("%s  ", recv_buff);                fflush(stdout);            }            printf("\n");        } else if (COMPARE(token, ==, "get")) {            char *data = strtok(NULL, delim);            char *send_data = packet("get", strlen(data) + 1, data);            send(sockfd, send_data, HEAD_SIZE+strlen(data)+1, 0);            free(send_data);            recvlen = recv(sockfd, recv_buff, 4, 0);            if (recvlen <= 0) break;            int size = *(int *)recv_buff;            memset(recv_buff, 0, 0);            recvlen = recv(sockfd, recv_buff, size, 0);            FILE *fp = fopen(data, "wb");            size_t len = fwrite(recv_buff, 1, recvlen, fp);            printf("file download\n");            fclose(fp);        } else if (COMPARE(token, ==, "put")) {            char *data = strtok(NULL, delim);            FILE *fp = fopen(data, "rb");            if (fp == NULL) {                printf("file open failed\n");                continue;            }            size_t readlen = fread(send_buff, 1, sizeof(send_buff), fp);            char *tmp = packet("put", readlen, send_buff);            send(sockfd, tmp, HEAD_SIZE+readlen, 0);            free(tmp);            fclose(fp);            memset(recv_buff, 0, 0);            recv(sockfd, recv_buff, 3, 0);            if (COMPARE(recv_buff, ==, "ok"))                 printf("put file finish\n");        } else if (COMPARE(token, ==, "quit")) {            close(sockfd);            return 0;        }#endif    }    close(sockfd);    return 0;}char *packet(const char *cmd, int size, const char *data) {    char *ret = malloc(sizeof(char *) + sizeof(int) + size);    memcpy(ret, cmd, 4);    *(int *)(ret + 4) = size;    if (size != 0)         memcpy(ret + HEAD_SIZE, data, size);    return ret;}

显示结果:
这里写图片描述

一个简单的ftp软件就实现了,不过有太多的缺陷和问题,等以后修改了再更新