unp.h
client..c
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h> /* for nonblocking */
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h> /* for S_xxx file mode constants */
#include <unistd.h>
#include <sys/wait.h>
#define SA struct sockaddr
#define SERV_PORT 9877
#define BLOCK 1024
typedef struct info
{
char data[BLOCK];
int length;
int no;
} Info;
server.c
#include "unp.h"
void wrapRecvPacket(int sockfd,int wno,int *flagAry,SA *cliaddr,socklen_t len)
{
fd_set rset;
while(1)
{
struct timeval tval;
tval.tv_sec = 3;
tval.tv_usec = 0;
FD_ZERO(&rset);
FD_SET(sockfd,&rset);
int n = select(sockfd+1,&rset,NULL,NULL,&tval);
if (n == 0)
{
printf("peer closed exit\n");
exit(0);
}
Info packet;
n = recvfrom(sockfd,&packet,sizeof(packet),0,cliaddr,&len);
if (n != sizeof(packet))
continue;
if (packet.no == -1)
{
puts("end flag");
sendto(sockfd,"end\0",4,0,cliaddr,len);
break;
}
else
{
printf("recv %d\n",packet.length);
lseek(wno,packet.no * BLOCK,SEEK_SET);
write(wno,packet.data,packet.length);
flagAry[packet.no] = 1;
}
}
}
int main(int argc, char const *argv[])
{
int sockfd;
struct sockaddr_in servaddr, cliaddr;
socklen_t len;
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);
bind(sockfd,(SA*) &servaddr,sizeof(servaddr));
char filename[10];
recvfrom(sockfd,filename,10,0,(SA*) &cliaddr,&len);
char segNumber[10];
recvfrom(sockfd,segNumber,10,0,(SA*) &cliaddr,&len);
int iseg = atoi(segNumber);
int *flagAry =(int*)malloc(sizeof(int) * iseg);
bzero(flagAry,sizeof(int)* iseg);
int wno = open(filename,O_WRONLY|O_CREAT, S_IRWXU);
wrapRecvPacket(sockfd,wno,flagAry,(SA*) &cliaddr,sizeof(cliaddr));
while (1)
{
int idx = 0;
int loseFlag = 0;
for (;idx < iseg;++idx)
{
if (flagAry[idx] == 0)
loseFlag = 1;
}
if (!loseFlag)
{
puts("ok");
sendto(sockfd,"OK\0",3,0,(SA*) &cliaddr,sizeof(cliaddr));
break;
}
else
{
puts("lose");
sendto(sockfd,"RET\0",4,0,(SA*) &cliaddr,sizeof(cliaddr));
sendto(sockfd,flagAry,sizeof(int) * iseg,0,(SA*) &cliaddr,sizeof(cliaddr));
wrapRecvPacket(sockfd,wno,flagAry,(SA*) &cliaddr,sizeof(cliaddr));
}
}
free(flagAry);
close(wno);
close(sockfd);
}
client..c
#include "unp.h"
int wrapSendPacket(int sockfd,int rno,int *tranAry,SA *servaddr,socklen_t len,int count,int debug)
{
int idx = 0;
Info info;
while(idx < count)
{
if (debug && idx == 3 || debug && idx == 4 || debug && idx == 5)
{
++idx;
continue;
}
bzero(&info,sizeof(info));
lseek(rno,tranAry[idx] * BLOCK,SEEK_SET);
int n = read(rno,info.data,BLOCK);
info.no = tranAry[idx++];
info.length = n;
sendto(sockfd,&info,sizeof(info),0,servaddr,len);
printf("send %d\n",info.length);
}
int times=0;
while(times < 3)
{
fd_set rset;
info.no = -1;
sendto(sockfd,&info,sizeof(info),0,servaddr,len);
struct timeval tval;
tval.tv_sec = 1;
tval.tv_usec = 0;
FD_ZERO(&rset);
FD_SET(sockfd,&rset);
int n = select(sockfd+1,&rset,NULL,NULL,&tval);
if(n > 0)
{
char reply[10];
recvfrom(sockfd,reply,10,0,(SA*) &servaddr,&len);
return 1;
}
++times;
}
return 0;
}
int main(int argc, char const *argv[])
{
int sockfd;
struct sockaddr_in servaddr;
socklen_t len;
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
sockfd = socket(AF_INET,SOCK_DGRAM,0);
char filename[10];
strcpy(filename,"1.rar");
int rno = open(filename,O_RDONLY);
char segNumber[10];
int iseg = lseek(rno,0,SEEK_END) / BLOCK;
if(lseek(rno,0,SEEK_END) % BLOCK != 0)
iseg = iseg + 1;
sprintf(segNumber,"%d", iseg);
sendto(sockfd,filename,strlen(filename),0,(SA*) &servaddr,sizeof(servaddr));
sendto(sockfd,segNumber,strlen(segNumber),0,(SA*) &servaddr,sizeof(servaddr));
lseek(rno,0,SEEK_SET);
int *tranAry = (int*)malloc(sizeof(int) * iseg);
int idx = 0;
for (;idx<iseg;++idx)
tranAry[idx] = idx;
int res = wrapSendPacket(sockfd,rno,tranAry,(SA*) &servaddr,sizeof(servaddr),idx,1);
if (res == 0)
exit(0);
char reply[10];
recvfrom(sockfd,reply,10,0,(SA*) &servaddr,&len);
if (!strcmp(reply,"OK"))
puts("tran ok");
else
{
int *flagAry = (int*)malloc(sizeof(int) * iseg);
bzero(flagAry,sizeof(int) * iseg);
recvfrom(sockfd,flagAry,sizeof(int) * iseg,0,(SA*) &servaddr,&len);
int idx,idy;
idx = idy = 0;
bzero(tranAry,sizeof(int) * iseg);
for (;idy<iseg;++idy)
{
if (flagAry[idy] == 0)
tranAry[idx++] = idy;
}
int res = wrapSendPacket(sockfd,rno,tranAry,(SA*) &servaddr,sizeof(servaddr),idx,0);
if (res == 0)
exit(0);
}
close(rno);
close(sockfd);
}