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

📄 tftp.c

📁 linux下的tftp socket编程样例
💻 C
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/stat.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <fcntl.h>#define TFTP_TIMEOUT 5             /* seconds */#define TFTP_RRQ   1#define TFTP_WRQ   2#define TFTP_DATA  3#define TFTP_ACK   4#define TFTP_ERROR 5#define TFTP_OACK  6static const char *tftp_bb_error_msg[] = {	"Undefined error",	"File not found",	"Access violation",	"Disk full or allocation error",	"Illegal TFTP operation",	"Unknown transfer ID",	"File already exists",	"No such user"};static inline int tftp(char *host, const char *remotefile, int localfd){	const int bb_tftp_num_retries = 5;	struct sockaddr_in sa;	struct sockaddr_in from;	struct timeval tv;	socklen_t fromlen;	fd_set rfds;	char *cp;	unsigned short tmp;	int socketfd;	int len;	int opcode = 0;	int finished = 0;	int timeout = bb_tftp_num_retries;	unsigned short block_nr = 1;	int port = htons (69);	/* Can't use RESERVE_CONFIG_BUFFER here since the allocation	 * size varies meaning BUFFERS_GO_ON_STACK would fail */	char *buf = malloc(516);	if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {		printf ("Create socket error\n");		exit (0);	}	len = sizeof (sa);	memset(&sa, 0, len);	bind(socketfd, (struct sockaddr *)&sa, len);	sa.sin_family = AF_INET;	sa.sin_port = port;	sa.sin_addr.s_addr = inet_addr (host);	/* build opcode */	opcode = TFTP_RRQ;	while (1) {		cp = buf;		/* first create the opcode part */		*((unsigned short *) cp) = htons(opcode);		cp += 2;		/* add filename and mode */		if (opcode == TFTP_RRQ) {                        int too_long = 0;			/* see if the filename fits into buf */			/* and fill in packet                */			len = strlen(remotefile) + 1;			if ((cp + len) >= &buf[515]) {			        too_long = 1;			} else {			        strncpy(cp, remotefile, len);				cp += len;			}			if (too_long || ((&buf[515] - cp) < 6)) {				printf ("too long remote-filename");				break;			}			/* add "mode" part of the package */			memcpy(cp, "octet", 6);			cp += 6;		}		/* add ack and data */		if (opcode == TFTP_ACK) {			*((unsigned short *) cp) = htons(block_nr);			cp += 2;			block_nr++;			printf ("block nr : %d\n", block_nr);		}		/* send packet */		timeout = bb_tftp_num_retries;  /* re-initialize */		do {			len = cp - buf;			if (sendto(socketfd, buf, len, 0, (struct sockaddr *) &sa, sizeof(sa)) < 0) {				printf ("send error\n");				len = -1;				break;			}			if (finished && (opcode == TFTP_ACK)) {				break;			}			/* receive packet */			memset(&from, 0, sizeof(from));			fromlen = sizeof(from);			tv.tv_sec = TFTP_TIMEOUT;			tv.tv_usec = 0;			FD_ZERO(&rfds);			FD_SET(socketfd, &rfds);			switch (select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) {			case 1:				len = recvfrom(socketfd, buf, 516, 0,						(struct sockaddr *) &from, &fromlen);				if (len < 0) {					printf ("recvfrom\n");					break;				}				timeout = 0;				if (sa.sin_port == port) {					sa.sin_port = from.sin_port;				}				if (sa.sin_port == from.sin_port) {					break;				}				/* fall-through for bad packets! */				/* discard the packet - treat as timeout */				timeout = bb_tftp_num_retries;			case 0:				printf ("timeout\n");				timeout--;				if (timeout == 0) {					len = -1;					printf ("last timeout");				}				break;			default:				printf ("select error\n");				len = -1;			}		} while (timeout && (len >= 0));		if ((finished) || (len < 0)) {			break;		}		/* process received packet */		opcode = ntohs(*((unsigned short *) buf));		tmp = ntohs(*((unsigned short *) &buf[2]));		if (opcode == TFTP_ERROR) {			char *msg = NULL;			if (buf[4] != '\0') {				msg = &buf[4];				buf[515] = '\0';			} else if (tmp < (sizeof(tftp_bb_error_msg)					  / sizeof(char *))) {				msg = (char *) tftp_bb_error_msg[tmp];			}			if (msg) {				printf ("server says: %s\n", msg);			}			break;		}		if (opcode == TFTP_DATA) {			if (tmp == block_nr) {							len = write(localfd, &buf[4], len - 4);				if (len < 0) {					printf ("write local file error\n");					break;				}				if (len != (512)) {					finished++;				}				opcode = TFTP_ACK;				continue;			}		}	}	return finished ? EXIT_SUCCESS : EXIT_FAILURE;}intmain(){	char *host = "192.168.0.254";	const char *localfile = "localfile";	const char *updateimage = "NET.C";	int result;	int fd;	/* figure out what to pass to getopt */	fd = open(localfile, O_WRONLY | O_CREAT);	if (fd < 0) {		printf ("local file error\n");		exit (0);	}	result = tftp(host, updateimage, fd);	return(result);}

⌨️ 快捷键说明

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