原创:如何做linux下udp大文件传输

发布于 2022-10-03 20:04:54 字数 21522 浏览 19 评论 0


近日小弟做了个linux下用户数据报协议大文件传输程式发上来与大家共勉。
代码在 redhat 9.0 下编译通过。
最大测试无差错传输文件:288M
最大测试传输速度:6.5M/S

可能这里并不需要这种类型的帖子,但希望各位能代小弟转贴,因为网络上很难搜索到这种可以解决丢包问题的代码级实现方法,希望每一个需要的人都能看的到。

服务器端:

  1. #include<sys/socket.h>;
  2. #include<string.h>;
  3. #include<netinet/in.h>;
  4. #include<stdio.h>;
  5. #include<stdlib.h>;
  6. #include<fcntl.h>;
  7. #include<sys/stat.h>;
  8. #include<unistd.h>;
  9. #include<errno.h>;
  10. #include<sys/select.h>;
  11. #include<sys/time.h>;
  12. #include<unistd.h>;
  13. #include<sys/types.h>;
  14. #define SERV_PORT 2500
  15. #define MAX_SIZE 1024*40
  16. void recvUDP(char name[20],int sockfd)
  17. {
  18.         int ret,fd;
  19.         mode_t fdmode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
  20.         char mesg[MAX_SIZE];
  21.         fd_set rdset;
  22.         struct timeval tv;
  23.         int rlen,wlen;
  24.         int i;
  25.         fd = open(name,O_RDWR|O_CREAT|O_APPEND,fdmode);
  26.         if(fd == -1)
  27.         {
  28.                 printf("open file %s error:%n",name,strerror(errno));
  29.                 exit(-1);
  30.         }
  31.         for(i=0;;i++)
  32.         {
  33.                 tv.tv_sec = 1;
  34.                 tv.tv_usec = 0;
  35.                 FD_ZERO(&rdset);
  36.                 FD_SET(sockfd,&rdset);
  37.                
  38.                 ret = select(sockfd+1,&rdset,NULL,NULL,&tv);
  39.                 if(ret == -1)
  40.                 {
  41.                         printf("select error %s\n",strerror(errno));
  42.                         exit(-1);
  43.                 }
  44.                 else if(ret==0)
  45.                 {
  46.                         printf("select timeout,continue circle\n");
  47.                         continue;
  48.                 }
  49.                
  50.                 if(FD_ISSET(sockfd,&rdset))
  51.                 {
  52.                         memset(mesg,0,MAX_SIZE);
  53.                         rlen = read(sockfd,mesg,MAX_SIZE);
  54.                         if(rlen <=0 )
  55.                         {
  56.                                 printf("read error %s\n",strerror(errno));
  57.                                 exit(-1);
  58.                         }
  59.                        
  60.                         if(!strcmp(mesg,"end"))
  61.                         {
  62.                                 printf("recv end.\n");
  63.                                 break;
  64.                         }
  65.                         wlen = write(fd,mesg,rlen);
  66.                         if(wlen != rlen )
  67.                         {
  68.                                 printf("write error %s\n",strerror(errno));
  69.                                 exit(-1);
  70.                         }       
  71.                 }
  72.                
  73.                 printf("The %d times write\n",i);
  74.         }
  75.         close(fd);
  76. }
  77. int main(int argc, char *argv[])
  78. {
  79.         int sockfd;
  80.         int r;
  81.         struct sockaddr_in servaddr;
  82.         sockfd = socket(AF_INET,SOCK_DGRAM,0); /*create a socket*/
  83.         /*init servaddr*/
  84.         bzero(&servaddr,sizeof(servaddr));
  85.         servaddr.sin_family = AF_INET;
  86.         servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  87.         servaddr.sin_port = htons(SERV_PORT);
  88.         /*bind address and port to socket*/
  89.         if(bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) == -1)
  90.         {
  91.                 perror("bind error");
  92.                 exit(-1);
  93.         }
  94.         r = fcntl(sockfd, F_GETFL, 0);
  95.         fcntl(sockfd, F_SETFL, r & ~O_NONBLOCK);
  96.        
  97.         recvUDP(argv[1],sockfd);
  98.         return 0;
  99. }

复制代码

客户端:

  1. #include<sys/types.h>;
  2. #include<sys/socket.h>;
  3. #include<string.h>;
  4. #include<netinet/in.h>;
  5. #include<stdio.h>;
  6. #include<stdlib.h>;
  7. #include<arpa/inet.h>;
  8. #include<fcntl.h>;
  9. #include<sys/stat.h>;
  10. #include<errno.h>;
  11. #include<sys/sysinfo.h>;
  12. #include<sys/select.h>;
  13. #include<sys/time.h>;
  14. #include<unistd.h>;
  15. #define MAX_SIZE 1024*40
  16. #define SERV_PORT 2500
  17. void connectUDP(char name[20],int sockfd,struct sockaddr *pservaddr,socklen_t servlen)
  18. {
  19.                 char buf[MAX_SIZE];
  20.                 fd_set wrset;
  21.                 struct timeval tv;
  22.                 int rlen,wlen;
  23.                 int fd;
  24.                 int ret;
  25.                 int i;
  26.                 if(connect(sockfd,(struct sockaddr *)pservaddr,servlen) == -1)
  27.                 {
  28.                         perror("connet error");
  29.                         exit(1);
  30.                 }
  31.                 else
  32.                         printf("connect server ok!\n");
  33.                 fd = open(name,O_RDONLY);
  34.                 if(fd==-1)
  35.                 {
  36.                         printf("fopen error %s\n",strerror(errno));
  37.                         exit(-1);
  38.                 }
  39.                
  40.                 i=0;
  41.                
  42.                 while(1)
  43.                 {       
  44.                         tv.tv_sec = 1;
  45.                         tv.tv_usec = 0;
  46.                        
  47.                         FD_ZERO(&wrset);
  48.                         FD_SET(sockfd,&wrset);
  49.                        
  50.                         ret = select(sockfd+1,NULL,&wrset,NULL,&tv);
  51.                         if(ret == -1)
  52.                         {
  53.                                 printf("select error %s\n",strerror(errno));
  54.                                 exit(-1);
  55.                         }
  56.                         else if(ret==0)
  57.                         {
  58.                                 printf("select timeout,continue circle\n");
  59.                                 continue;
  60.                         }
  61.                        
  62.                         memset(buf,0,MAX_SIZE);
  63.                         if(FD_ISSET(sockfd,&wrset))
  64.                         {                                       
  65.                                 rlen = read(fd,buf,MAX_SIZE);
  66.                                 if(rlen <0)
  67.                                 {
  68.                                         printf("fread data error %s\n",strerror(errno));
  69.                                         exit(-1);
  70.                                 }
  71.                                 else if(rlen==0)
  72.                                 {
  73.                                         wlen = write(sockfd,"end",3);
  74.                                         if(wlen !=3)
  75.                                         {
  76.                                                 printf("write end error\n",strerror(errno));
  77.                                                 exit(-1);
  78.                                         }
  79.                                         printf("all complete\n");
  80.                                         close(fd);
  81.                                         close(sockfd);
  82.                                         exit(0);
  83.                                 }
  84.                                 wlen = write(sockfd,buf,rlen);
  85.                                 if(wlen != rlen)
  86.                                 {
  87.                                         printf("write data to sockfd error:%s\n",strerror(errno));
  88.                                         exit(-1);
  89.                                 }
  90.                                
  91.                                 i++;
  92.                                
  93.                                 usleep(500);
  94.                                 printf("The %d times read\n",i);
  95.                         }
  96.                 }
  97.         }
  98. int main(int argc ,char *argv[])
  99. {       
  100.         char *fh;
  101.         struct sysinfo s_info;
  102.         float time1,time2;
  103.         int error1,error2;
  104.         int sockfd;
  105.         struct stat fsize;
  106.         struct sockaddr_in servaddr;
  107.         error1= sysinfo(&s_info);
  108.         time1 = s_info.uptime;
  109.         int r;
  110.         if(argc != 3)
  111.         {
  112.                 printf("useage:udpclient<IPaddress>;\n");
  113.                 exit(1);
  114.         }
  115.         bzero(&servaddr,sizeof(servaddr));
  116.         servaddr.sin_family= AF_INET;
  117.         servaddr.sin_port = htons(SERV_PORT);
  118.        
  119.         if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0)
  120.         {
  121.                 printf("[%s]is not a valid IPaddress\n",argv[1]);
  122.                 exit(1);
  123.         }
  124.         fh = argv[2];
  125.         sockfd =socket(AF_INET,SOCK_DGRAM,0);
  126.        
  127.         r = fcntl(sockfd, F_GETFL, 0);
  128.         fcntl(sockfd, F_SETFL, r & ~O_NONBLOCK);
  129.        
  130.         connectUDP(argv[2],sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));       
  131.         fprintf(stderr,"ServerIP:\t%s\n",argv[1]);       
  132.         if(stat(argv[2],&fsize) == -1)
  133.                 perror("failed to get fiel statusi\n");
  134.         else       
  135.                 fprintf(stderr,"file name:\t%s\nfile size:\t%dK\n",argv[2],fsize.st_size/1024);
  136.         error2=sysinfo(&s_info);
  137.         time2 = s_info.uptime;
  138.         printf("tranfice file time =%fs\n",(time2-time1));
  139. }               

复制代码

Makefile

  1. all:send recv
  2. send:send.c
  3.         gcc -Wall send.c -o send
  4. recv:recv.c
  5.         gcc -Wall recv.c -o recv
  6.        
  7. clean:
  8.         rm -rf send recv

复制代码

[ 本帖最后由 platinum 于 2006-5-12 12:02 编辑 ]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

风透绣罗衣 2022-10-10 20:04:54

希望大家可以转到任何可以转的linux论坛。谢谢!

醉梦枕江山 2022-10-10 20:04:54

大哥不会是让我们都当做范例学习吧.

苦行僧 2022-10-10 20:04:54

赞一下LZ

孤单情人 2022-10-10 20:04:54

请楼主以后发代码时,用 [ code ] 括起来,或者禁止显示表情,否则贴出的代码没法看

笔芯 2022-10-10 20:04:54

memset是多此一举,并且大大耗费时间。

旧人九事 2022-10-10 20:04:54

很好啊,值得学习!

谢谢楼主。

放血 2022-10-10 20:04:54

为什么说这是 "可以解决丢包问题的代码级实现方法"??

哪里是亮点,lz讲明白点不好吗??

否则我读代码的时候会遗漏过去体会不到.

还有如果网络状况很差 或者 发送比接收的机器速度快 等情况下是否会能保证不丢报呢?

ぇ气 2022-10-10 20:04:54

原帖由 思一克 于 2006-5-12 13:11 发表
memset是多此一举,并且大大耗费时间。

agree.

抚笙 2022-10-10 20:04:54

无知者无畏亚

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文