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

📄 tftp.c

📁 Linux下C实现的ftp客户端代码
💻 C
字号:
/* achieve base function of tftp client.Some bugs are in the file,
 *  if you know how to correct them,please tell me,thank you!
 *  All rights reserved.
 *  Author : xiaoleng
 *  Email   : flylgh@163.com
 *  create date: 2008-11-1
 *
 *  实现TFTP客户端基本功能,但本实现未设置接收超时!
 *  BUG(如果设置了超时,将在接收到8M数据的时候出错)
 *  如果你知道如何改正,或者你有更好的建议,请通知我。
 *  对你无私的精神,我表示衷心的感谢!
 *  你可以随意发布、修改,但请别用于学习或者交流的其他
 *  用途! 
 *  作者 : xiaoleng
 *  Email   : flylgh@163.com
 *  创建时间: 2008-11-1
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <time.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>

#include "tftpc.h"

typedef struct 
{
	unsigned short option;
	unsigned short number;
	char data[512];
}tftp_package;

typedef struct
{
	struct timeval timeout;	
	struct sockaddr_in server_addr;
	int sockfd;
	char trans_mode[10];	
}tftp_information;


tftp_information tftp_info;


static int create_req_buf(int option,char *file_name,char *buf_out)
{
	char *pre_addr = buf_out;
	*buf_out++ = 0;
	*buf_out++ = option;
	strcpy(buf_out,file_name);
	buf_out += strlen(file_name);
	*buf_out++ = 0;
	strcpy(buf_out,tftp_info.trans_mode);
	buf_out += strlen(tftp_info.trans_mode);
	*buf_out++ = 0;

	return (buf_out-pre_addr);
}

static int send_ack(unsigned short ack_num)
{
	tftp_package package;
	int retval;

	memset(&package,0,sizeof(package));
	package.option = htons(OP_ACK);
	package.number = ack_num;
	retval = sendto(tftp_info.sockfd,&package,4,0,(struct sockaddr *)&tftp_info.server_addr,sizeof(struct sockaddr));
	if(retval == -1){
		return -1;
	}

	return 0;
}

static int read_file(char *file_name)
{
	int retval,fd,len,size,n_read,seq_no=1;
	int datalen;
	char buf[520];
	tftp_package package;
	fd_set readfd;

	memset(buf,0,520);
	len = create_req_buf(OP_READ,file_name,buf);
	retval = sendto(tftp_info.sockfd,buf,len,0,(struct sockaddr *)&tftp_info.server_addr,sizeof(struct sockaddr));
	if(retval == -1){
		perror("send to errno:");
		return -1;
	}
	
	chdir(DEFAULT_DIR);
	fd = open(file_name,O_CREAT | O_RDWR |O_TRUNC,0666);

	len = sizeof(struct sockaddr);
	size = sizeof(package);
	memset(&package,0,size);
	FD_ZERO(&readfd);
	FD_SET(tftp_info.sockfd,&readfd);
	do{
		//retval = select(tftp_info.sockfd+1,&readfd,NULL,NULL,&tftp_info.timeout);
		retval = 1;
		if(retval > 0){
			n_read = recvfrom(tftp_info.sockfd,&package,size,0,(struct sockaddr *)&tftp_info.server_addr,(unsigned int *)&len);
			if(ntohs(package.option) == OP_DATA){
				datalen = n_read - 4;
				if(ntohs(package.number) != seq_no){
					continue;
				}
				if(send_ack(package.number) == -1){
					printf("send ack error!\n");
					continue;
				}
				if(seq_no == 65535){
					seq_no = 0;
				}else{
					seq_no ++;
				}

				if(datalen > 0){
					write(fd,package.data,datalen);
				}
				if(datalen < 512){
					printf("receive complete\n");
					retval = 0;
					break;
				}
			}
			else if(ntohs(package.option) == OP_ERROR){
				seq_no ++;
				printf("%s\n",package.data);
				retval = -1;
				break;
			}
		}
		else if(retval == 0){
			printf("receive time out!\n");
			retval = -1;
		}
		else{
			perror("function[select]error:");
			retval = -1;
		}
	}while(retval > 0);

	printf("seq_no[%d]\n",seq_no);
	close(fd);
	return retval;
}


static int write_file(char *file_name)
{


	return 0;
}


static void tftp_init(char *server_ip)
{
	tftp_info.sockfd = socket(AF_INET,SOCK_DGRAM,0);
	tftp_info.timeout.tv_sec = TFTP_SEND_RECV_TIMEOUT;
	tftp_info.timeout.tv_usec = 0;
	tftp_info.server_addr.sin_family = AF_INET;
	tftp_info.server_addr.sin_port = htons(69);
	tftp_info.server_addr.sin_addr.s_addr = inet_addr(server_ip);
	memset(tftp_info.trans_mode,0,sizeof(tftp_info.trans_mode));
	strcpy(tftp_info.trans_mode,MODE_OCTET);
}

static void tftp_free(void)
{
	close(tftp_info.sockfd);
}


int tftp_user_req(char *server_ip,int option,char *file_name)
{
	int result;

	tftp_init(server_ip);
	switch(option)
	{
		case OP_READ:
			result = read_file(file_name);
			break;
		case OP_WRITE:
			result = write_file(file_name);
			break;
		default:
			result = -1;
			break;	
	}
	tftp_free();
	return result;
}










⌨️ 快捷键说明

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