⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udpechoserverdemo.c

📁 一个LINUX环境下的udp 的回显示服务器
💻 C
字号:
/* udp echo server demo */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcntl.h>#include "tftpc.h"static inline char conv_char(char ch){	ch = ch & 0xff;	if((ch < 0x20) || ((unsigned char)ch > 0x7f))		return '.';		return ch;}void dump_mem(const char *tip, void *base, int size){	unsigned char *p = base;	int rows = size / 16;	int rest = size % 16;	int i, j;	printf("[%s len = %d]\n", tip, size);	for(i = 0; i < rows; i++) {		printf("0x%p:", p);		for(j = 0; j < 16; j++)			printf("%02X ", p[j]);		printf("|");		for(j = 0; j < 16; j++)			printf("%c", conv_char(*p++));		printf("\n");	}	printf("0x%p:", p);	for(j = 0; j < rest; j++)		printf("%02X ", p[j]);	for(;j < 16; j++)		printf("   ");	printf("|");	for(j = 0; j < rest; j++)		printf("%c", conv_char(p[j]));	printf("\n");}size_t read_with_select(int fd, void *buffer, size_t size, int flags, struct sockaddr *addr, socklen_t *addrlen, int tout){    #include <sys/time.h>    fd_set rd_fds;    struct timeval timeout;    timeout.tv_sec = tout;    timeout.tv_usec = 0;    FD_ZERO(&rd_fds);    FD_SET(fd,&rd_fds);    if(select(fd + 1, &rd_fds, NULL, NULL, &timeout) > 0)    {			return recvfrom(fd, buffer, size, flags, addr, addrlen);	}	return -1;}size_t send_to(int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t addrlen){	dump_mem("SEND", buf, len);	return sendto(sockfd, buf, len, flags, addr, addrlen);}size_t recv_from(int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen, int tout){	if(tout == 0)		tout = 20;	*addrlen = sizeof(struct sockaddr);	len = read_with_select(sockfd, buf, len, flags, addr, addrlen, tout);	dump_mem("RECV", buf, len);	return len;}int make_req(char *outbuf, int rw, char *filename, int blksize, int timeout){	char *p = &outbuf[2];	outbuf[0] = 0x00;	outbuf[1] = rw;	strcpy(p, filename);	p += (strlen(filename) + 1);	strcpy(p, "octet");	p += (strlen("octet") + 1);	//----------------------------------->	strcpy(p, "tsize");	p += (strlen("tsize") + 1);	strcpy(p, "0");	p += (strlen("0") + 1);	//<-----------------------------------	//----------------------------------->	if((blksize >= 8) && (blksize <= 65464))	{		strcpy(p, "blksize");		p += (strlen("blksize") + 1);		sprintf(p, "%d", blksize);		p += (strlen(p) + 1);	}	//<-----------------------------------	//----------------------------------->	if(timeout > 0)	{		strcpy(p, "timeout");		p += (strlen("timeout") + 1);		sprintf(p, "%d", timeout);		p += (strlen(p) + 1);	}	//<-----------------------------------	return (int)p - (int)outbuf;}int parse_oack(char *oack, int len, int *tsize, int *blksize, int *timeout){	char *p = oack + 2;	len -= 2;	/* Reset to default value*/	*tsize = -1;	*blksize = 512;	*timeout = 2;	while(len > 0)	{		switch(p[1])		{			case 's':			// tsize				if(strcmp(p, "tsize") == 0)				{					len -= 6;					p += 6;					*tsize = atoi(p);					len -= (strlen(p) + 1);					p += (strlen(p) + 1);				}				else					return -1;				break;			case 'l':			// blksize				if(strcmp(p, "blksize") == 0)				{					len -= 8;					p += 8;					*blksize = atoi(p);					len -= (strlen(p) + 1);					p += (strlen(p) + 1);				}				else					return -1;				break;			case 'i':			// timeout				if(strcmp(p, "timeout") == 0)				{					len -= 8;					p += 8;					*timeout = atoi(p);					len -= (strlen(p) + 1);					p += (strlen(p) + 1);				}				else					return -1;				break;			default:				return -1;				break;		}	}	return 0;}int make_ack(char *outbuf, char *package, int *blknumber){	switch(package[1])	{		case TFTP_OPC_DATA:			memcpy(outbuf, package, 4);			outbuf[1] = TFTP_OPC_ACK;			*blknumber = ntohs(*((unsigned short*)&package[2]));			break;		case TFTP_OPC_OACK:			memset(outbuf, 0, 4);			outbuf[1] = TFTP_OPC_ACK;			*blknumber = 0;			break;		case TFTP_OPC_ERROR:			break;	}	return package[1];}int send_req(int sockfd, char *ip, unsigned short port, int rw, char *filename, int blksize, int timeout){	unsigned char buffer[512];	struct sockaddr_in srvAddr;	socklen_t len;	bzero(&srvAddr, sizeof(srvAddr));	srvAddr.sin_family = AF_INET;	srvAddr.sin_port = htons(port);	inet_pton(AF_INET, ip, &srvAddr.sin_addr.s_addr);	len = make_req(buffer, rw, filename, blksize, timeout);	if(send_to(sockfd, buffer, len, 0, (struct sockaddr*)&srvAddr, sizeof(srvAddr)) < 0)	{		close(sockfd);		perror("send faild! maybe the server is down!");		exit(1);	}	return 0;}int send_err(int sockfd, int errno, struct sockaddr_in *srvAddr){	unsigned char errmsg[100];	errmsg[0] = 0x00;	errmsg[1] = TFTP_OPC_ERROR;	errmsg[2] = 0x00;	errmsg[3] = errno;	strcpy(&errmsg[4], errlist[errno].errmsg);	return send_to(sockfd, errmsg, strlen(errlist[errno].errmsg) + 5, 0, (struct sockaddr*)srvAddr, sizeof(srvAddr));}void usage(const char *tip){	printf("%s", tip);	printf(	"Usage:\n"					\			"	tftpc ip file [/p:port] [/b:blksize] [/t:timeout]\n"	\	);}void parse_param(int argc, char *argv[], unsigned short *port, int *timeout, int *blksize){	int port_is_set = 0;	int tsize_is_set = 0;	int blksize_is_set = 0;	if(argc < 3)	{		usage("argument err!\n");		exit(1);	}	while(argc > 3)	{		argc--;		if(argv[argc][0] != '/')		{			usage("argument err!\n");			exit(1);		}		switch(argv[argc][1])		{			case 't':				if(tsize_is_set)				{					usage("invalid timeout value!\n");					exit(1);				}				tsize_is_set = 1;				*timeout = atoi(&argv[argc][3]);				break;			case 'b':				if(blksize_is_set)				{					usage("invalid block size!\n");					exit(1);				}				blksize_is_set = 1;				*blksize = atoi(&argv[argc][3]);				break;			case 'p':				if(port_is_set)				{					usage("invalid port number!\n");					exit(1);				}				port_is_set = 1;				*port = atoi(&argv[argc][3]);				break;			default:				usage("unknown argument!\n");				exit(1);				break;		}	}}int main(int argc, char *argv[]){	int sockfd;	char *srvIP = argv[1];	unsigned short port = 69;	char *filename = argv[2];	int tsize = 0;	int blksize = 512;	int timeout = 3;	unsigned char recvBuf[2048];	int blknumber = 0;	int start_data_transfer = 0;	char ack[4];	int len;	parse_param(argc, argv, &port, &timeout, &blksize);	sockfd = socket(AF_INET, SOCK_DGRAM, 0);	if(sockfd < 0)	{		perror("Invalid socket");		exit(1);	}	send_req(sockfd, srvIP, port, TFTP_OPC_READ, filename, blksize, timeout);	while(1)	{		struct sockaddr_in srvAddr;		socklen_t remoteAddrLen;		int blkn;		len = recv_from(sockfd, recvBuf, 2048, 0, (struct sockaddr*)&srvAddr, &remoteAddrLen, timeout);		if(len <= 0)		{			static int retry = 0;			if(retry > 3)			{				printf("Retry %d times, give up!\n", retry);				exit(1);			}			printf("block %d timeout, retry(%d)\n", blknumber, retry);			if(start_data_transfer)			{				sendto(sockfd, ack, 4, 0, (struct sockaddr*)&srvAddr, sizeof(srvAddr));			}			else			{				send_req(sockfd, srvIP, port, TFTP_OPC_READ, filename, blksize, timeout);			}			retry++;			continue;		}		int op_code = make_ack(ack, recvBuf, &blkn);		if(op_code == TFTP_OPC_OACK)		{			start_data_transfer = 1;			parse_oack(recvBuf, len, &tsize, &blksize, &timeout);			if(send_to(sockfd, ack, 4, 0, (struct sockaddr*)&srvAddr, sizeof(srvAddr)) < 0)			{				close(sockfd);				perror("send faild! maybe the server is down!");				exit(1);			}		}		else if(op_code == TFTP_OPC_DATA)		{			start_data_transfer = 1;			len -= 4;			if(++blknumber < blkn)			{				send_err(sockfd, TFTP_ERRC_UNKNOWNID, &srvAddr);				break;			}			if(send_to(sockfd, ack, 4, 0, (struct sockaddr*)&srvAddr, sizeof(srvAddr)) < 0)			{				close(sockfd);				perror("send faild! maybe the server is down!");				exit(1);			}			if(tsize > 0)			{				tsize -= len;			}			if(tsize == 0)				break;			if(len < blksize)				break;		}		else if(recvBuf[1] == TFTP_OPC_ERROR)			break;	}	close(sockfd);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -