linux c UDP文件传输 添加了丢包处理

unp.h
#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);
}


猜你喜欢

转载自blog.csdn.net/lewiskyo/article/details/39337923