2007年8月20日星期一

如何做linux下udp大文件传输




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

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

服务器端:



#include<sys/socket.h>;
#include<string.h>;
#include<netinet/in.h>;
#include<stdio.h>;
#include<stdlib.h>;
#include<fcntl.h>;
#include<sys/stat.h>;
#include<unistd.h>;
#include<errno.h>;
#include<sys/select.h>;
#include<sys/time.h>;
#include<unistd.h>;
#include<sys/types.h>;

#define SERV_PORT 2500
#define MAX_SIZE 1024*40


void recvUDP(char name[20],int sockfd)
{
int ret,fd;
mode_t fdmode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
char mesg[MAX_SIZE];
fd_set rdset;
struct timeval tv;
int rlen,wlen;
int i;

fd = open(name,O_RDWR|O_CREAT|O_APPEND,fdmode);
if(fd == -1)
{
printf("open file %s error:%n",name,strerror(errno));
exit(-1);
}

for(i=0;;i++)
{
tv.tv_sec = 1;
tv.tv_usec = 0;

FD_ZERO(&rdset);
FD_SET(sockfd,&rdset);

ret = select(sockfd+1,&rdset,NULL,NULL,&tv);
if(ret == -1)
{
printf("select error %s\n",strerror(errno));
exit(-1);
}
else if(ret==0)
{
printf("select timeout,continue circle\n");
continue;
}

if(FD_ISSET(sockfd,&rdset))
{
memset(mesg,0,MAX_SIZE);
rlen = read(sockfd,mesg,MAX_SIZE);
if(rlen <=0 )
{
printf("read error %s\n",strerror(errno));
exit(-1);
}

if(!strcmp(mesg,"end"))
{
printf("recv end.\n");
break;
}

wlen = write(fd,mesg,rlen);
if(wlen != rlen )
{
printf("write error %s\n",strerror(errno));
exit(-1);
}
}

printf("The %d times write\n",i);
}

close(fd);
}

int main(int argc, char *argv[])
{
int sockfd;
int r;
struct sockaddr_in servaddr;

sockfd = socket(AF_INET,SOCK_DGRAM,0); /*create a socket*/

/*init servaddr*/
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);

/*bind address and port to socket*/
if(bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) == -1)
{
perror("bind error");
exit(-1);
}

r = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, r & ~O_NONBLOCK);

recvUDP(argv[1],sockfd);

return 0;

}

客户端:

CODE:
#include<sys/types.h>;
#include<sys/socket.h>;
#include<string.h>;
#include<netinet/in.h>;
#include<stdio.h>;
#include<stdlib.h>;
#include<arpa/inet.h>;
#include<fcntl.h>;
#include<sys/stat.h>;
#include<errno.h>;
#include<sys/sysinfo.h>;
#include<sys/select.h>;
#include<sys/time.h>;
#include<unistd.h>;

#define MAX_SIZE 1024*40
#define SERV_PORT 2500


void connectUDP(char name[20],int sockfd,struct sockaddr *pservaddr,socklen_t servlen)
{
char buf[MAX_SIZE];
fd_set wrset;
struct timeval tv;
int rlen,wlen;
int fd;
int ret;
int i;

if(connect(sockfd,(struct sockaddr *)pservaddr,servlen) == -1)
{
perror("connet error");
exit(1);
}
else
printf("connect server ok!\n");

fd = open(name,O_RDONLY);
if(fd==-1)
{
printf("fopen error %s\n",strerror(errno));
exit(-1);
}

i=0;

while(1)
{
tv.tv_sec = 1;
tv.tv_usec = 0;

FD_ZERO(&wrset);
FD_SET(sockfd,&wrset);

ret = select(sockfd+1,NULL,&wrset,NULL,&tv);
if(ret == -1)
{
printf("select error %s\n",strerror(errno));
exit(-1);
}
else if(ret==0)
{
printf("select timeout,continue circle\n");
continue;
}

memset(buf,0,MAX_SIZE);
if(FD_ISSET(sockfd,&wrset))
{
rlen = read(fd,buf,MAX_SIZE);
if(rlen <0 )
{
printf("fread data error %s\n",strerror(errno));
exit(-1);
}
else if(rlen==0)
{
wlen = write(sockfd,"end",3);
if(wlen !=3)
{
printf("write end error\n",strerror(errno));
exit(-1);
}

printf("all complete\n");

close(fd);
close(sockfd);
exit(0);
}

wlen = write(sockfd,buf,rlen);
if(wlen != rlen)
{
printf("write data to sockfd error:%s\n",strerror(errno));
exit(-1);
}

i++;

usleep(500);
printf("The %d times read\n",i);
}
}
}


int main(int argc ,char *argv[])
{
char *fh;
struct sysinfo s_info;
float time1,time2;
int error1,error2;
int sockfd;
struct stat fsize;
struct sockaddr_in servaddr;
error1= sysinfo(&s_info);
time1 = s_info.uptime;
int r;

if(argc != 3)
{
printf("useage:udpclient<IPaddress>;\n");
exit(1);
}
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family= AF_INET;
servaddr.sin_port = htons(SERV_PORT);

if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0)
{
printf("[%s]is not a valid IPaddress\n",argv[1]);
exit(1);
}
fh = argv[2];

sockfd =socket(AF_INET,SOCK_DGRAM,0);

r = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, r & ~O_NONBLOCK);

connectUDP(argv[2],sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
fprintf(stderr,"ServerIP:\t%s\n",argv[1]);
if(stat(argv[2],&fsize) == -1)
perror("failed to get fiel statusi\n");
else
fprintf(stderr,"file name:\t%s\nfile size:\t%dK\n",argv[2],fsize.st_size/1024);
error2=sysinfo(&s_info);
time2 = s_info.uptime;
printf("tranfice file time =%fs\n",(time2-time1));
}

Makefile

[Copy to clipboard] [ - ]
CODE:
all:send recv

send:send.c
gcc -Wall send.c -o send
recv:recv.c
gcc -Wall recv.c -o recv

clean:
rm -rf send recv

没有评论: