http://bbs.chinaunix.net/thread-633761-1-1.html
近日小弟做了個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);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
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;
}
用戶端:
#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
- 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