免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 14299 | 回复: 16

原创:如何做linux下udp大文件传输 [复制链接]

论坛徽章:
0
发表于 2005-10-25 15:22 |显示全部楼层

近日小弟做了个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 编辑 ]

论坛徽章:
0
发表于 2005-10-25 16:08 |显示全部楼层

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

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

论坛徽章:
5
IT运维版块每日发帖之星
日期:2015-08-06 06:20:00IT运维版块每日发帖之星
日期:2015-08-10 06:20:00IT运维版块每日发帖之星
日期:2015-08-23 06:20:00IT运维版块每日发帖之星
日期:2015-08-24 06:20:00IT运维版块每日发帖之星
日期:2015-11-12 06:20:00
发表于 2005-10-25 21:45 |显示全部楼层

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

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

论坛徽章:
0
发表于 2006-05-12 11:46 |显示全部楼层
赞一下LZ

论坛徽章:
0
发表于 2006-05-12 12:03 |显示全部楼层
请楼主以后发代码时,用 [ code ] 括起来,或者禁止显示表情,否则贴出的代码没法看

论坛徽章:
0
发表于 2006-05-12 13:11 |显示全部楼层
memset是多此一举,并且大大耗费时间。

论坛徽章:
0
发表于 2006-05-12 13:18 |显示全部楼层
很好啊,值得学习!

谢谢楼主。

论坛徽章:
0
发表于 2006-05-12 13:50 |显示全部楼层
为什么说这是 "可以解决丢包问题的代码级实现方法"??

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

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

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

论坛徽章:
0
发表于 2006-05-12 15:31 |显示全部楼层
原帖由 思一克 于 2006-5-12 13:11 发表
memset是多此一举,并且大大耗费时间。


agree.

论坛徽章:
0
发表于 2006-05-13 14:15 |显示全部楼层
无知者无畏亚
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP