C语言实现FTP(C/S)协议(ls命令和download命令)用两个端口实现(命令端口和数据端口)

来源:互联网 发布:网络侦探攻略第十九章 编辑:程序博客网 时间:2024/05/21 12:42

Server:


#include <stdio.h>

#include <stdlib.h>

#include <sys/socket.h>

#include <unistd.h>//sleep();

#include <netinet/in.h>

#include <arpa/inet.h>

#include <string.h>

#include<dirent.h>

#include <fcntl.h>

#define SERVER_NET_PORT 4396

#define TRANSPORT_PORT 8888

int initSocket(struct sockaddr_in * in,int sizeOfIn,int port){

    int sock;

    if ((sock = socket(AF_INET,SOCK_STREAM,0)) == -1) {

        printf("创建原始套接字出错!\n");

        exit(1);//异常退出1/-1,正常退出0

    }

    //封装地址:(为本机地址)

    in->sin_addr.s_addr = inet_addr("0.0.0.0");

    in->sin_family = AF_INET;

    in->sin_port = htons(port);

    //bind连接socket与ip:

    if (bind(sock, (struct sockaddr *)in, sizeOfIn) !=0) {

        printf("bind error!\n");

        exit(1);

    }

    

    return sock;

}

void server_ls(int sock,char * recExCmd){

    char sendBuf[1024];

    DIR * d = opendir(recExCmd);

    struct dirent * e;

    while ((e=readdir(d))) {

        if (e->d_name[0]!='.') {

//            printf("write %s\n",e->d_name);

            char a[5] ="\n";

//            write(sock, sendBuf, sizeof(sendBuf));

//            strcat(e->d_name, a);

            strcat(sendBuf, e->d_name);

            strncat(sendBuf, a, 1);

        }

    }

    if (write(sock, sendBuf, sizeof(sendBuf)) < 0) {

        printf("write error!\n");

    }else

        printf("write %s",sendBuf);

}

void serverDownload(int sock,char * recExCmd){

    int openfd;

    char readBuf[1024];

    if ((openfd=open(recExCmd, O_RDONLY)) == -1) {

        printf("open error!\n");

        close(openfd);

    }else{//opened!

        ssize_t readLen;

        //这里用循环是因为可能缓冲区不够容纳整个文件:

        while ((readLen=read(openfd, readBuf, sizeof(readBuf))) > 0) {

            if (write(sock, readBuf, readLen)<0) {

                printf("Open file error!");

                break;

            }

            //将缓冲区清空:

            memset(readBuf, 0, sizeof(readBuf));

        }

        close(openfd);

    }

    close(sock);

}

int createSockFunc(int acceptfd,int port){

    //创建套接字:

    int transportAccept;

    int transportSock;

    struct sockaddr_in transportIn;

    struct sockaddr_in recAddr;

    socklen_t recAddrLen = sizeof(recAddr);

    transportSock = initSocket(&transportIn, sizeof(transportIn),port);

    //监听:

    if (listen(transportSock, 5) != 0) {

        printf("listen error!\n");

        exit(1);

    }

    printf("Established port=%d!\n",port);

    //将transportSock的端口信息发送给客户端:

    char portInchar[10];

    sprintf(portInchar, "%d",port);

    if (write(acceptfd, portInchar, sizeof(portInchar)) < 0) {

        printf("send port error!\n");

    }

    printf("port sent!\n");

    while ((transportAccept = accept(transportSock,(struct sockaddr*)&recAddr, &recAddrLen)) != -1) {

        printf("Accept from : %s\n",inet_ntoa(recAddr.sin_addr));

        break;

    }

    return transportAccept;

}

int main(int argc,const char * argv[]) {

    //Server Septs:

    /*

     1.创建socket

     2.循环监听

     */

    //创建流套接字:

    char recBuf[1024];//

    struct sockaddr_in receiveAddr;//

    int accceptFd;//

    socklen_t receiveAddrLen = sizeof(receiveAddr);

    struct sockaddr_in in;

    int sock;

    //创建套接字:

    sock = initSocket(&in,sizeof(in),SERVER_NET_PORT);

    //监听:

    if (listen(sock, 5) != 0) {

        printf("listen error!\n");

        exit(1);

    }

    printf("Established port=%d!\n",SERVER_NET_PORT);

    while ((accceptFd = accept(sock, (struct sockaddr *)&receiveAddr, &receiveAddrLen)) != -1) {

        printf("来自 %s 的连接!\n",inet_ntoa(receiveAddr.sin_addr));

        //连接成功处理信息:(无线程版本)

        ssize_t len;

        if ((len=read(accceptFd, recBuf, sizeof(recBuf))) < 0) {

            printf("read error!\n");

        }

        printf("recBuf is %s ,len is %ld\n",recBuf,len);

        if (0 == strncmp(recBuf,"server_ls", 9)) {

            printf("****ls_server****\n");

            server_ls(accceptFd,recBuf+10);

            printf("****Finished****\n");

        }else if (0 == strncmp(recBuf,"download", 8)) {

            printf("****download****\n");

            int transSock;

            transSock = createSockFunc(accceptFd,TRANSPORT_PORT);

            serverDownload(transSock,recBuf+9);

            printf("****Finished****\n");

        }else if (0 == strncmp(recBuf,"upload", 6)){

            

        }else{

            printf("cmd wrong!\n");

        }

    }

    

    return 0;

}

Client:

.h>

#include <stdlib.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <unistd.h>//close();

#include <string.h>

#include <dirent.h>

#include <fcntl.h>

#define SERVER_NET_ADDR "45.77.207.215"

#define SERVER_NET_PORT 4396

#define INPUT_SIZE 50

//不能用这个返回的原因是:char dest是一个局部变量,in stack,执行完就会释放空间,所以返回值永远是NULL

//char * analyse(char * input){

//    char dest[50];

//    char * p;

//    int sizeOfInput = sizeof(input)-2;

//    strncpy(dest, input+3,sizeOfInput);//深复制

//    p=dest;

////    printf("%p \n %p \n",p,input+3);

//    return p;

//}

int initSock(struct sockaddr_in *addr,int port){

    int sockfd;

    if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) == -1) {

        printf("创建原始套接字出错!\n");

        exit(1);//异常退出1/-1,正常退出0

    }

    //这两种方式都可以将char*类型的地址转换成网络字节序:

    addr->sin_addr.s_addr = inet_addr(SERVER_NET_ADDR);

    //    inet_pton(AF_INET, SERVER_NET_ADDR, &addr.sin_addr);

    addr->sin_family = AF_INET;

    addr->sin_port = htons(port);

    return sockfd;

}

void showServer(char * input,int sockfd){

    ssize_t readLen;

    char getResponce[1024];

    if (write(sockfd, input, INPUT_SIZE) < 0) {

        printf("write error!\n");

        exit(1);

    }

    printf("Files are:\n");

    if ((readLen=read(sockfd, getResponce, sizeof(getResponce))) < 0) {

        printf("server_ls responce error!\n");

        exit(1);

    }

//    printf("readlen=%ld\n",readLen);

    printf("%s",getResponce);//自带"\n"

    

}

void recFile(int sock,char * input){

    int openFd;

    char readBuf[1024];

    char path[100] ="/Users/ron/Desktop/servers.rtf";

    if ((openFd=open(path, O_WRONLY|O_CREAT,0666)) == -1) {

        printf("open error!\n");

    }else{//opened!

        ssize_t readLen;

        while ((readLen=read(sock, readBuf, sizeof(readBuf))) >0) {

            if (write(openFd, readBuf, readLen) <0) {

                printf("write error!\n");

                close(openFd);

            }

        }

        close(openFd);

    }

    close(sock);

}

void download(char * input,int sockfd){

    struct sockaddr_in in;

    int sock;

    ssize_t readLen;

    //

    char recPort[10];

    if (write(sockfd, input, INPUT_SIZE) < 0) {

        printf("write error!\n");

        exit(1);

    }

    //等待服务器回应(主要是等待服务器开辟的端口信息):

    if ((readLen = read(sockfd, recPort, sizeof(recPort))) <0) {

        printf("read server port error!\n");

    }else{

        printf("read size: %ld,and port: %s\n",readLen,recPort);

        //初始化客户端套接字:

        sock = initSock(&in, atoi(recPort));

        while (connect(sock, (struct sockaddr *)&in,sizeof(in)) != 0) {

            perror("Connect error!\n");

            close(sock);

        }

        printf("Connect!\n");

        //接收文件:

        recFile(sock,input);

    }

}

void checkCommand(char * input,int sockfd){

    if(NULL == input)

    {

        printf("checkCommand error!\n");

        exit(1);

    }

    else

    {

        if(0 == strncmp(input,"ls",2)) {

            //列出本地文件列表指令

            printf("****ls****\n");

            DIR * dir = opendir(input+3);//

            struct dirent *ep;

            while((ep =readdir(dir)))

            {

                if(ep->d_name[0] !='.')

                {

                    printf("%s\n",ep->d_name);

                }

            }

            printf("**********\n");

        }else if(0 == strncmp(input,"server_ls", 9)){

            printf("****ls_server****\n");

            showServer(input,sockfd);

            printf("**********\n");

        }else if(0 == strncmp(input,"quit",4)){

            //断开链接指令

//            close(sockfd);

//            exit(0);//正常退出

            printf("Quit!\n");

        }else if(0 == strncmp(input,"download_", 9)){

            //从服务器下载文件指令

            printf("****download****\n");

            download(input,sockfd);

            printf("********\n");

        }else{

            printf("command wrong!\n");

        }

    }

}

int main(int argc,const char * argv[]) {

    /*Step:

     1.创建socket

     2.connect

     */

    int sockfd;

    struct sockaddr_in addr;

    if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) == -1) {

        printf("创建原始套接字出错!\n");

        exit(1);//异常退出1/-1,正常退出0

    }

    //这两种方式都可以将char*类型的地址转换成网络字节序:

    addr.sin_addr.s_addr = inet_addr(SERVER_NET_ADDR);

    //    inet_pton(AF_INET, SERVER_NET_ADDR, &addr.sin_addr);

    addr.sin_family = AF_INET;

    addr.sin_port = htons(SERVER_NET_PORT);

    if ((connect(sockfd, (struct sockaddr*)&addr,sizeof(addr))) != 0) {

        perror("Connect error!\n");

        close(sockfd);

        exit(-1);

    }

    //连接成功!:

    printf("Connected to server!\n");

    printf("*********Operation Help*********\n");  //操作帮助

    printf("显示本地xxx路径文件列表:        ls_xxx\n");

    printf("显示服务器xxx路径文件列表:      server_ls_xxx\n");

    printf("实现xxx文件读取与上传:   upload_xxx\n");

    printf("实现xxx文件下载与存储:   download_xxx\n");

    printf("断开socket链接:          quit\n");

    printf("********************************\n");

    printf("Please input:\n");

    char input[INPUT_SIZE];

    scanf("%s",input);//这种输入方式不能有空格

    checkCommand(input,sockfd);

    close(sockfd);

    return 0;

}



原创粉丝点击