项目1 tftp的上传和下载

1.代码

#include <head.h>
#define ERR_MSG(msg) do{\
    fprintf(stderr,"line: %d\n",__LINE__);\
    perror(msg);\
    return -1;\
}while(0);

#define IP "192.168.8.249"
//#define IP "192.168.74.186"
//#define IP "192.168.0.226"

#define PORT 69

//文件的打开
int file(char *filename);
int file1(char *filename);
void mume();
int main(int argc,const char * argv[])
{
    //创建报式字节套
    int sfd = socket(AF_INET,SOCK_DGRAM,0);
    if(sfd < 0){
        ERR_MSG("socket");
        return -1;
    }

    //先写给客户端找到所谓的连接
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORT);
    sin.sin_addr.s_addr = inet_addr(IP);
    socklen_t len = sizeof(sin);

    //把tftp的临时端口信息留在新的结构体中
    struct sockaddr_in cin;
    socklen_t len1 = sizeof(cin);

    char buf[128] = "";
    char str[128] = "";
    char filename[30] = "";
    int res = 0;
    int res1 = 0;
    //文件名
    int fd = -1;

    char buff[800] = "";
    unsigned short st = 0;
    unsigned short st1 = 0;
    int sum = 0;
    while(1){
        mume();
        printf("选择(输入0,1,2)--->");
        scanf("%d",&sum);
        switch(sum){
            case 0://退出
                close(fd);
                close(sfd);
                printf("退出成功\n");
                return 0;
            case 1://下载
                {
                    TEXT:
                    memset(filename,0,sizeof(filename));
                    printf("请输入需要下载的文件名\n");
                    scanf("%s",filename);
                    // strcpy(rw.buf,buf);


                    // 文件名传入服务器上
                    res = sprintf(buff,"%c%c%s%c%s%c",0,1,filename,0,"octet",0);
                    if(res < 0){
                        ERR_MSG("sprintf");
                        return -1;
                    }


                    //发送文件给服务器收到信息
                    res = sendto(sfd,buff,res,0,(struct sockaddr*)&sin,len);
                    if(res < 0){
                        ERR_MSG("sendto");
                        return -1;
                    }


                    //下载    
                    while(1){
                        //接收信息并判断是否为正确的信息并退出且保存在目录下
                        //读第一次的数据
                        memset(buff,0,sizeof(buff));
                        res1 = recvfrom(sfd,buff,sizeof(buff),0,(struct sockaddr*)&cin,&len1);
                        if(res < 0){
                            ERR_MSG("recvfrom");
                            return -1;
                        }
                        //第一次的数据包的解析如果是错误的就之间回头写文件名
                        if(5 == *((char*)buff+1)){
                        if(1 == ntohs(*((unsigned short*)buff+1))){
                            printf("错误码是[%d] 错误信息是[%s]",(*((char*)buff+1)),(char*)(buff+4));
                            printf("请重新输入文件名\n");
                            goto TEXT;
                        }
                        printf("错误码是[%d] 错误信息是[%s]",(ntohs(*((unsigned short*)buff+1))),(char*)(buff+4));
                        return -1;
                        }

                        //可以执行到这就是正确的文件
                        //在这步打开文件并写入
                        if(1 ==  ntohs(*((unsigned short*)buff+1))){
                            fd = file(filename);
                        }
                        // printf("buff = %ld\n",strlen(buff));
                        //写入到文件中
                        //到达这里就是需要给对面回复ACK和保存在本目录下
                        write(fd,(char*)(buff+4),res1-4);

                        //如果小于516bt就相当于文件传输结束
                        //回复ACK
                        buff[1] = 4;
                        res = sendto(sfd,buff,4,0,(struct sockaddr*)&cin,len1);
                        if(res < 0){
                            ERR_MSG("sendto");
                            return -1;
                        }
                        if( 1 != ntohs(*((unsigned short*)buff+1))){
                            if(res1 < 516){
                                printf("文件下载完成\n");
                                break;
                            }
                        }
                    }
                    

                }
                break;
            case 2://上传
                {
                    TEXT1:
                    memset(filename,0,sizeof(filename));
                    printf("请输入需要上传的文件名\n");
                    scanf("%s",filename);
                    // strcpy(rw.buf,buf);


                    // 文件名传入服务器上判断是否存在存在重新输入
                    res = sprintf(buff,"%c%c%s%c%s%c",0,2,filename,0,"octet",0);
                    if(res < 0){
                        ERR_MSG("sprintf");
                        return -1;
                    }
                    // printf("%s __%d__\n",buff,__LINE__);
                    //发送文件给服务器收到信息
                    res = sendto(sfd,buff,res,0,(struct sockaddr*)&sin,len);
                    if(res < 0){
                        ERR_MSG("sendto");
                        return -1;
                    }
                    //上传
                    while(1){
                        //收ack如果第一次收到时是正确的码那就读并上传
                        memset(buff,0,sizeof(buff));
                        res1 = recvfrom(sfd,buff,sizeof(buff),0,(struct sockaddr*)&cin,&len1);
                        if(res1 < 0){
                            ERR_MSG("recvfrom");
                            return -1;
                        }
                        //printf("%d __%d__\n",ntohs(*(short*)buff),__LINE__);
                        //第一次的ACK的解析如果是错误且文件存在的就之间回头写文件名
                        if(5 == ntohs(*(short*)buff)){
                            if(6 == ntohs(*((unsigned short*)buff+1))){
                                printf("错误码是[%d] 错误信息是[%s]",(*((char*)buff+1)),(char*)(buff+4));
                                printf("文件已经存在,请重新输入文件名\n");
                                goto TEXT1;
                            }
                            printf("错误码是[%d] 错误信息是[%s]",(ntohs(*((unsigned short*)buff+1))),(char*)(buff+4));
                            return -1;
                        }
                        //如果收到APK后是对的且上次读到的数据比516少就退出
                        if( 0 != ntohs(*((unsigned short*)buff+1))){
                            if(res < 516){
                                printf("文件上传完成\n");
                                break;
                            }
                        }
                        //可以执行到这就是正确的需要上传的文件
                        //在这步打开文件并读取
                        if(0 ==  ntohs(*((unsigned short*)buff+1))){
                            fd = file1(filename);
                            if(fd < 0||0 == fd){
                                printf("需要上传的文件不存在\n");
                                goto TEXT1;
                            }
                        }
                        // printf("buff = %ld\n",strlen(buff));
                        //写入到文件中
                        //到达这里就是需要给对面回复ACK和保存在本目录下
                        res = read(fd,(char*)(buff+4),512);
                        if(res < 0){
                            ERR_MSG("read");
                            return -1;
                        }
                        //printf("%d __%d__\n",res,__LINE__);
                        //printf("%s\n",(char*)buff+4);
                        //如果小于516bt就相当于文件传输结束


                        //传递数据包
                        buff[1] = 3;
                        buff[3] = buff[3] +1;
                        res = sendto(sfd,buff,res+4,0,(struct sockaddr*)&cin,len1);
                        if(res < 0){
                            ERR_MSG("sendto");
                            return -1;
                        }
                    }
                }
                break;
        }
        getchar();
        printf("<-----请输入enter键清除该页面----->\n");
        getchar();
    }


    return 0;
}
//打开文件
int file(char *filename){
    int fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
    if(fd < 0){
        ERR_MSG("open");
        return -1;
    }
    return fd;
}
int file1(char *filename){
    int fd = open(filename,O_RDONLY);
    return fd;
}
void mume(){
    system("clear");
    printf("--------------------------------------\n");
    printf("--------------------------------------\n");
    printf("--------------0.退出------------------\n");
    printf("--------------1.下载------------------\n");
    printf("--------------2.上传------------------\n");
    printf("--------------------------------------\n");
    printf("--------------------------------------\n");
}

下载 

 上传

 

 

 

退出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值