linux下tftp server的一种简易实现
2012-09-22 14:33
176 查看
转自:http://blog.chinaunix.net/uid-11911430-id-2801536.html
博主:经测试,能够使用
最近学习LINUX socket编程,利用socket实现了一个Linux下命令行的tftp客户端,此客户端只可以从TFTP服务器获取文件。使用格式为:./tftpget <ipaddr> <filename>。该程序可以运行在Linux的PC机上,也可以运行在嵌入式开发板上(需交叉编译)。程序的源代码及其注释如下:
博主:经测试,能够使用
最近学习LINUX socket编程,利用socket实现了一个Linux下命令行的tftp客户端,此客户端只可以从TFTP服务器获取文件。使用格式为:./tftpget <ipaddr> <filename>。该程序可以运行在Linux的PC机上,也可以运行在嵌入式开发板上(需交叉编译)。程序的源代码及其注释如下:
/************************************************* * 这个程序实现了TFTP客户端,在Linux上编译通过并 * * 正常使用。使用socket编程,具体的TFTP协议由于 * * 篇幅太长,这里没有列出来,可以参考网址: * * http://www.faqs.org/rfcs/rfc1350.html * ************************************************/ #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <netdb.h> #include <string.h> //下面定义的几个宏是TFTP协议的操作码,参考协议 #define OP_RRQ 1 //读请求 #define OP_WRQ 2 //写请求 #define OP_DATA 3 //数据包 #define OP_ACK 4 //确认包 #define OP_ERROR 5 //错误信息 //TFTP错误信息编码 static char *error_string[] = { "Not defined error!", //0 "File not found!", //1 "Access denied!", //2 "Disk full or allocation exceeded!", //3 "Illegal TFTP operation!", //4 "Unknown transfer ID!", //5 "File already exists!", //6 "No such user!" //7 }; int main(int argc, char **argv) { int socketFD; //socket描述符 struct sockaddr_in tftpServer, tftpClient; //自身和服务器的socket信息 FILE *fp; //用于保存本地文件 char buffer[516]; //网络通信用的buffer int addrlen; int lastPacket, currentPacket; //包计数 unsigned short *s_ptr; char *c_ptr; int tmp; int ret; if (argc < 3) { //使用方式 printf("Usage: %s <ipaddr> <filename>\n", argv[0]); return 0; } //创建socket socketFD = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == socketFD) { printf("Can not create socket!\n"); return 0; } //客户端自身信息 bzero(&tftpClient, sizeof (tftpClient)); tftpClient.sin_family = AF_INET; tftpClient.sin_addr.s_addr = INADDR_ANY; tftpClient.sin_port = htons(0); //绑定socket到本机IP地址 tmp = bind(socketFD, (struct sockaddr *)&tftpClient, sizeof (tftpClient)); if (0 != tmp) { printf("Can not bind socket!\n"); goto error_1; } //服务器信息 bzero(&tftpServer, sizeof (tftpServer)); addrlen = sizeof (tftpServer); tftpServer.sin_family = AF_INET; tftpServer.sin_addr.s_addr = inet_addr(argv[1]); tftpServer.sin_port = htons(69); //TFTP服务端口 s_ptr = (unsigned short *)&buffer[0]; *s_ptr = htons(OP_RRQ); //操作码 c_ptr = &buffer[2]; strcpy(&buffer[2], argv[2]); //远程文件名 c_ptr += strlen(argv[2]); *c_ptr++ = 0; strcpy(c_ptr, "netascii"); //模式 c_ptr += 8; *c_ptr++ = 0; //创建一个本地文件 fp = fopen(argv[2], "w"); if (NULL == fp) { printf("Can not create locale file!\n"); goto error_1; } lastPacket = 0; while (1) { //发送请求或者回应包到服务器 tmp = sendto(socketFD, buffer, c_ptr - &buffer[0], 0, (struct sockaddr *)&tftpServer, sizeof (tftpServer)); if (-1 == tmp) { printf("Can not send buffer!\n"); goto error_2; return 0; } //从服务器获取数据包 tmp = recvfrom(socketFD, buffer, 516, 0, (struct sockaddr *)&tftpServer,&addrlen); if (-1 == tmp) { printf("Receive data error!\n"); goto error_2; return 0; } else { switch (ntohs(*s_ptr)) { //数据包 case OP_DATA: currentPacket = ntohs(*(s_ptr+1)); //验证包的顺序 if ((lastPacket + 1) != currentPacket) { printf("ERROR: packet error!\n"); goto error_2; } lastPacket = currentPacket; tmp -= 4; //写入数据到本地文件 ret = fwrite(&buffer[4], 1, tmp, fp); if (tmp != ret) { printf("ERROR: write to local file error!\n"); goto error_2; } //如果等于512则不是最后一个包 if (512 != tmp) { goto read_ok; } //准备返回信息 *s_ptr = htons(OP_ACK); *(s_ptr + 1) = htons(currentPacket); c_ptr = &buffer[4]; break; //服务器返回错误信息 case OP_ERROR: //根据错误码,打印错误信息 printf("ERROR: %s\n", error_string[ntohs(*(s_ptr+1))]); goto error_2; break; //发生其他未知错误 default: printf("ERROR: Unknow error!\n"); goto error_2; break; } } } read_ok: fclose(fp); close(socketFD); return 0; error_2: fclose(fp); unlink(argv[2]); error_1: close(socketFD); return 0; } |
相关文章推荐
- 一种ACM评判内核简易实现 使用C# WEB调用C++编译器的方法
- 一种更为简易的tab实现
- [Delphi] 实现自动化对象的一种简易方法
- 一种“邻居环”的简易实现
- Java回调的一种简易实现
- IOC的一种简易实现(四)
- shuffle算法的一种简易实现
- 通用对象池ObjectPool的一种简易设计和实现方案
- IOC的一种简易实现
- IOC的一种简易实现(二)
- 一种简易数字波形存储器的实现
- Flask:API的一种简易实现方式——MethodView
- 一种实现人工智能程序自进化的概念原理
- 利用socket实现简易聊天程序
- 一种在单片机上实现多个软件定时功能的框架
- 使用 HttpClient 和 HtmlParser 实现简易爬虫
- rsa初识【php实现简易加解密】
- 简易记事本实现与分析(三)主界面
- vbs实现的简易评分程序
- 一种整数数据压缩存储的算法实现