基于UDP的文件传输程序代码

news/2024/5/18 11:52:30 标签: udp, 网络协议, 网络

1、基于UDP的TFTP文件传输

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<string.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#define ERR_MSG(msg) do{\
    fprintf(stderr,"%d",__LINE__);\
    perror("msg");\
}while(0)

#define SER_IP "192.168.2.131"
#define SER_PORT 69

#define CLI_IP "192.168.0.111"
#define CLI_PORT 7777


void Download();

void Upload();




int main(int argc, const char *argv[])
{
    int option =-1;
    while(1)
    {
        printf("************************\n");
        printf("********1、下载*********\n");
        printf("********2、上传*********\n");
        printf("********3、退出*********\n");
        printf("************************\n");
        printf("************************\n");
        scanf("%d",&option);
        while(getchar() != 10);
        if(1 == option)
            Download();
        else if(2 == option)
            Upload();
        else if(3 == option)
            break;
    }


    //关闭
    return 0;
}


void Download()
{
    //创建报式套接字
    int cfd = socket(AF_INET,SOCK_DGRAM,0);
    if(cfd < 0)
    {
        ERR_MSG("socket");
        return;
    }

    char buf[516]={0};

    //创建填充服务器地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family      = AF_INET;
    sin.sin_port        = htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);

    socklen_t addrlen = sizeof(sin);

    //设置读请求
    *(short*)buf = htons(1);
    //printf("%hd\t__%d__\n",ntohs(*(short*)buf),__LINE__);

    //将文件名写入到buf中
    printf("请输入要下载的文件名>>>>>>\n");
    scanf("%s",buf+2);
    while(getchar() != 10);
    char pathname[128]="";
    strcpy(pathname,buf+2);

    strcpy(buf+2+strlen(buf+2)+1,"octet");

    //printf("%hd %s %s\n",ntohs(*(short*)buf),buf+2,buf+2+strlen(buf+2)+1);     




    char *p1 = buf+2+strlen(buf+2)+1;
    int size = 4 + strlen(buf+2)+strlen(p1)+1;
    //发送数据
    if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
    {
        ERR_MSG("sendto");
        return;
    }
    printf("发送成功   size=%d\n",size);

    ssize_t res = 0,num = -1;
    short count=1;

    int fd = -1;;
    while(1)
    {
        //接收数据
        bzero(buf,sizeof(buf));
        res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&addrlen);
        if(res < 0)
        {
            ERR_MSG("recvfrom");
            return;
        }
        //  printf("[%s:%d]: %s\n",inet_ntoa(rcvaddr.sin_addr),ntohs(rcvaddr.sin_port),buf);
        //  printf("%d : %d\t%s\n",ntohs(*(short*)buf),ntohs(*(short*)(buf+2)),buf+4);
        if(ntohs(*(short*)buf) == 3)
        {
            if(1 == ntohs(*(short*)(buf+2)))
            {
                //创建文件
                fd = open(pathname,O_WRONLY|O_CREAT|O_TRUNC,0664);
                if(fd < 0)
                {
                    ERR_MSG("open");
                    return;
                }
            }

            if(ntohs(*(short*)(buf+2)) == count)
            {
                num = write(fd,buf+4,res-4);
                if(num < 0)
                {
                    ERR_MSG("read");
                    break;
                }
                else if(num < 512)
                {
                    printf("Download sucess\n");
                    break;
                }
                //发送数据
                bzero(buf,sizeof(buf));
                *(short *)buf = htons(4);
                *((short *)(buf+2))=htons(count++);

                if(sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
                {
                    ERR_MSG("sendto");
                    return ;
                }
            }
        }
        else if(ntohs(*(short *)buf) == 5)
        {
            printf("%s  __%d__\n",buf+4,__LINE__);
            break;
        }
        //  printf("发送成功\n");

    }
    close(fd);
    close(cfd);

}
void Upload()
{
    //创建报式套接字
    int cfd = socket(AF_INET,SOCK_DGRAM,0);
    if(cfd < 0)
    {
        ERR_MSG("socket");
        return;
    }

    char buf[516]={0};

    //创建填充服务器地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family      = AF_INET;
    sin.sin_port        = htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);

    socklen_t addrlen = sizeof(sin);


    //设置写请求
    *(short*)buf = htons(2);
    //printf("%hd\t__%d__\n",ntohs(*(short*)buf),__LINE__);

    //将文件名写入到buf中
    printf("请输入要上传的文件名>>>>>>\n");
    scanf("%s",buf+2);
    while(getchar() != 10);
    char pathname[128]="";
    strcpy(pathname,buf+2);

    strcpy(buf+2+strlen(buf+2)+1,"octet");

//  printf("%hd %s %s\n",ntohs(*(short*)buf),buf+2,buf+2+strlen(buf+2)+1);     
    char *p1 = buf+2+strlen(buf+2)+1;
    int size = 4 + strlen(buf+2)+strlen(p1)+1;
    //发送数据
    if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
    {
        ERR_MSG("sendto");
        return;
    }
    printf("发送成功   size=%d\n",size);

    ssize_t res = 0,num = -1;
    short count=0;
    int flag = 1;
    int fd = -1;;
    while(1)
    {
        //接收数据
        bzero(buf,sizeof(buf));
        res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&addrlen);
        if(res < 0)
        {
            ERR_MSG("recvfrom");
            return;
        }
    //  printf("*****%d*****%d*****\n",ntohs(*(short*)buf),ntohs(*(short*)(buf+2)));
        if(ntohs(*(short *)buf) == 5)
        {
            printf("*******************%d  __%d__\n",ntohs(*(short*)(buf+2)),__LINE__);
            break;
        }
        //  printf("[%s:%d]: %s\n",inet_ntoa(rcvaddr.sin_addr),ntohs(rcvaddr.sin_port),buf);

        else if(ntohs(*(short*)buf) == 4)
        {
            if(flag == 1)
            {
                //创建文件
                fd = open(pathname,O_RDONLY);
                if(fd < 0)
                {
                    ERR_MSG("open");
                    return;
                }
                flag = 0;
            }

            if(ntohs(*(short*)(buf+2)) != count)
            {
                lseek(fd,512*(ntohs(*(short*)(buf+2))),SEEK_SET);
                count = ntohs(*(short*)(buf+2));
            }

            if(ntohs(*(short*)(buf+2)) == count)
            {
        //      printf("%s",buf+4);
                bzero(buf,sizeof(buf));
                //发送数据
                *(short *)buf = htons(3);
                *((short *)(buf+2))=htons(++count);
                res = read(fd,buf+4,512);
                if(res < 0)
                {
                    ERR_MSG("read");
                    break;
                }
                ///
                if(count ==5)
                    count++;        //手动产生错误包,修改文件偏移量后读取数据并发送
                ///
        //      printf("%d : %d\t%s\n",ntohs(*(short*)buf),ntohs(*(short*)(buf+2)),buf+4);
                if(res == 0)
                {
                    printf("Update sucess\n");
                    break;
                }
                if(sendto(cfd,buf,res+4,0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
                {
                    ERR_MSG("sendto");
                    return ;
                }
            }

        }

        //  printf("发送成功\n");

    }
    close(fd);
    close(cfd);

}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

ubuntu@ubuntu:TFTP$ gcc 02_udpCli_TFTP.c 
ubuntu@ubuntu:TFTP$ ./a.out 
************************
********1、下载*********
********2、上传*********
********3、退出*********
************************
1
请输入要下载的文件名>>>>>>
5.png
1 5.png octet
发送成功   size=15
Download sucess
************************
********1、下载*********
********2、上传*********
********3、退出*********
************************
^C
ubuntu@ubuntu:TFTP$ ls
02_udpCli_TFTP.c  2       5      a.out  asd.c     d         huahua.c
1.png             2octet  5.png  asd    asdoctet  dict.txt
ubuntu@ubuntu:TFTP$ eog 5.png
ubuntu@ubuntu:TFTP$ 
 


http://www.niftyadmin.cn/n/225949.html

相关文章

系统升级 | RK3568开发平台成功搭载SylixOS国产实时操作系统

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

C语言—实用调试技巧

实用调试技巧什么是bug&#xff1f;调试是什么&#xff1f;有多重要&#xff1f;什么是调试调试的基本步骤Debug和Release的介绍Windows环境调试介绍调试环境的准备快捷键的使用调试的时候查看程序当前信息查看断点信息查看临时变量的值查看局部变量的值查看内存信息查看汇编信…

22勤于思考:gRPC都有哪些优势和不足?

如果你能从专栏的开篇词开始读到这篇文章并且能够在过程中认真思考,那么我相信你目前已经能够对gRPC有了较为充分了解。在专栏的最后几节中,我们抽出一篇文章。来探讨一下gRPC有哪些优势和不足,因为只有这样我们才能取其精华,去其糟粕,学习gRPC框架设计的优点,还能反观出…

m3u8视频文件破解爬取教程(请尊重知识产权,切勿违法),该方法需要基础开发知识

// UserScript // name media-source-extract // namespace https://github.com/Momo707577045/media-source-extract // version 0.8.2 // description https://github.com/Momo707577045/media-source-extract 配套插件 // author Momo707577045 // i…

【JavaEE】计算机组成以及操作系统(进程)的基本知识

目录 前言 1、计算机基本组成 1.1、存储器 2、操作系统 2.1、 进程&#xff08;任务&#xff09;的概念 2.2、进程的管理 2.2.1、进程控制块PCB&#xff08;process control block&#xff09; 2.3、CPU分配&#xff08;进程调度&#xff09; 2.3.1、并发 2.3.2、并…

02 捕获所有异常

1 捕获所有异常 通过 Exception 捕获所有异常&#xff0c;并调用它从其基类 Throwable 继承的方法进一步了解当然异常的类型。 package com.hcong.exceptions;/*** Classname ExceptionMethods* Date 2023/4/15 16:45* Created by HCong*/ public class ExceptionMethods {pu…

Linux下安装navicat

1.在https://www.navicat.com.cn/download/navicat-premium下载navicat安装包 2.在终端执行命令 给navicat16-premium-cs.AppImage赋予可执行的权限 chmod x navicat16-premium-cs.AppImage 启动Navicat16 ./navicat16-premium-cs.AppImage 3.点击连接——mysql——输入连…

快手社招Java后端开发岗面试,被问麻了

社招面试是基于你的工作项目来展开问的&#xff0c;比如你项目用了 xxx 技术&#xff0c;那么面试就会追问你项目是怎么用 xxx 技术的&#xff0c;遇到什么难点和挑战&#xff0c;然后再考察一下这个 xxx 技术的原理。 今天就分享一位快手社招面经&#xff0c;岗位是后端开发&…