如何基于c语言tftp服务器与客户端实现.docx
- 文档编号:25315940
- 上传时间:2023-06-07
- 格式:DOCX
- 页数:14
- 大小:66.64KB
如何基于c语言tftp服务器与客户端实现.docx
《如何基于c语言tftp服务器与客户端实现.docx》由会员分享,可在线阅读,更多相关《如何基于c语言tftp服务器与客户端实现.docx(14页珍藏版)》请在冰豆网上搜索。
如何基于c语言tftp服务器与客户端实现
如何基于c语言tftp服务器与客户端实现
本篇文章主要的内容就是教大家,如何基于c语言tftp服务器与客户端实现,是非常精彩的内容,希望对大家的学习之路有所帮助。
TFTP(TrivialFileTransferProtocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。
端口号为69。
开发环境:
ubuntu
所用知识点:
c,socket,tcp/ip协议
A)本实验主要实现tftp协议的服务器与客户端。
服务器实现功能有:
1)接收处理客户端请求,上传下下载文件
2)进行用户验证
3)对传输数据进行加密解密处理
4)生成日志文件
客户端实现功能有:
1)向服务器发出请求,上传或下载文件
2)对传输数据加密解密
3)对用户信息进行MD5加密
B)相关代码实现:
宏定下:
#ifndefMAKEWORD
#defineMAKEWORD(l,h)((unsignedshort)(((unsignedchar)(l))|(((unsignedshort)(unsignedchar)(h))<<8)))
#endif
#defineWSA_MAJOR_VERSION1
#defineWSA_MINOR_VERSION1
#defineWSA_VERSIONMAKEWORD(WSA_MAJOR_VERSION,WSA_MINOR_VERSION)
#defineTFTP_OCTET1
#defineTFTP_WSTAT_FIRSTACK0
#defineTFTP_WSTAT_NEXTACK1
#defineTFTP_WSTAT_LASTACK2
#defineTFTP_RRQ1//读请求
#defineTFTP_WRQ2//写请求
#defineTFTP_DATA3//数据
#defineTFTP_ACK4//ACK
#defineTFTP_ERROR5//Error
#defineMAX_RETRY3//最大重复次数
#defineTFTP_NOTEND_DATALEN512+2+2//数据块长度
//错误种类
#defineNot_defined0
#defineFile_not_found1
#defineAccess_violation2
#defineDisk_full3
#defineIllegal_TFTP_operation4
#defineUnknown_port5
#defineFile_already_exists6
#defineNo_such_user7
#defineTime_out8
#defineRead_file_Error9
#defineCannot_create_file10
#definepasswd_or_user_error11
包的填充:
#include"define.h"
#include
#include
intmakeack(unsignedshortnum,char*buffer,intsize);
intmakedata(unsignedshortnum,char*data,intdatasize,char*buffer,intbufsize);
intmakeerr(unsignedshortnum,char*buffer);
//ACK包填充
intmakeack(unsignedshortnum,char*buffer,intsize)
{
intpos=0;
buffer[pos]=0;
pos++;
buffer[pos]=TFTP_ACK;//操作码为04
pos++;
buffer[pos]=(char)(num>>8);//块号2个字节
pos++;
buffer[pos]=(char)num;
pos++;
returnpos;
}
//Data包填充
intmakedata(unsignedshortnum,char*data,intdatasize,char*buffer,intbufsize)
{
intpos=0;
buffer[pos]=0;
pos++;
buffer[pos]=TFTP_DATA;//操作码为03
pos++;
buffer[pos]=(char)(num>>8);//块号
pos++;
buffer[pos]=(char)num;
pos++;
memcpy(&buffer[pos],data,datasize);//填充数据
pos=pos+datasize;
returnpos;
}
//ERROR包填充
intmakeerr(unsignedshortnum,char*buffer)
{
intpos=0;
buffer[pos]=0;
pos++;
buffer[pos]=TFTP_ERROR;//操作码为05
pos++;
buffer[pos]=(char)(num>>8);//错误种类号
pos++;
buffer[pos]=(char)num;
pos++;
returnpos;
}
日志log.c实现
#include
staticcharlog[100];//日志
chardatetime[20];//记录时间变量
inttimeout=2,retran=3;//服务器参数
voidrecord(inta,structsockaddr_in*sin,char*file)
{
chartem[60];
time_tt=time(0);//初始化日历时间
strftime(datetime,sizeof(datetime),"%y/%m/%d%X",localtime(&t));//将时间格式化
strcat(log,datetime);//将时间写入记录
//将字符串格式化
bzero(&tem,sizeof(tem));
if(a==1)
sprintf(tem,"收到来自%s上传文件%s的请求。
\n",inet_ntoa(sin->sin_addr),file);
if(a==2)
sprintf(tem,"%s上传文件%s完毕。
\n",inet_ntoa(sin->sin_addr),file);
if(a==3)
sprintf(tem,"收到来自%s下载文件%s的请求。
\n",inet_ntoa(sin->sin_addr),file);
if(a==4)
sprintf(tem,"%s下载文件%s完毕。
\n",inet_ntoa(sin->sin_addr),file);
if(a==5)
sprintf(tem,"出现出错,操作中断。
\n",inet_ntoa(sin->sin_addr),file);
//将具体信息写入记录
strcat(log,tem);
FILE*write;
if((write=fopen("log.txt","a+"))==NULL)
printf("打开记录文件失败\n");
//将记录写入文件
fwrite(&log,strlen(log),1,write);
fclose(write);
bzero(&log,sizeof(log));
}
加密解密实现
#include
#include
#include
intdecrypt(FILE*in,FILE*out);
intencrypt(FILE*in,FILE*out);
unsignedcharatoh(char*hexstr);
intencrypt(FILE*in,FILE*out)
{
if(in==NULL||out==NULL)
{
fprintf(stderr,"%s\n","fileerror!
\n");
return-1;
}
unsignedcharhex;
while(fread(&hex,1,1,in))
{
hex=~hex^0x98;
fprintf(out,"%02X",hex);
}
return0;
}
intdecrypt(FILE*in,FILE*out)
{
if(in==NULL||out==NULL)
{
fprintf(stderr,"%s\n","fileerror!
");
return-1;
}
unsignedcharhexstr[3];
unsignedcharhex=0;
inti=0;
while(fread(hexstr,2,1,in))
{
hex=atoh(hexstr);
hex=~(hex^0x98);
fwrite(&hex,1,1,out);
}
return0;
}
/*convertstringtohex*/
unsignedcharatoh(char*hexstr)
{
inti;
inthextodec[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
charchtodec[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
unsignedcharhexnum=0;
for(i=0;i { if(hexstr[0]==chtodec[i]) { hexnum+=hextodec[i]*16; } } for(i=0;i { if(hexstr[1]==chtodec[i]) { hexnum+=hextodec[i]; } } returnhexnum; } 上传数据: //上传函数 voidupload(structsockaddr_insour_addr,charbuffer[]) { charsend_buffer[1024]={0}; charrecv_buffer[1024]={0}; structsockaddr_indest_addr; structtimevaltimeout={10,0}; intsour_len=0; intret=0; intlen=0; intflen=0; fd_setfdr; unsignedshortlastdata=0; unsignedshortblocknum=0; FILE*file; FILE*decrypt_file=NULL; charfilename[256]; //获取文件名 strcpy(filename,buffer+2); dest_addr.sin_family=AF_INET; dest_addr.sin_port=sour_addr.sin_port; dest_addr.sin_addr.s_addr=inet_addr(desthost);// //如果本地存在同名文件 if((file=fopen(filename,"rb"))! =NULL) { //发送一个error包,报告存在同名文件 printf("***存在同名文件***"); len=makeerr(File_already_exists,send_buffer); ret=sendto(sock,send_buffer,len,0,(structsockaddr*)&dest_addr,sizeof(dest_addr)); record(5,&sour_addr,filename); return; } //建立文件 if((file=fopen(filename,"w+b"))==NULL) { //如果失败,发送error包 printf("创建文件失败\n"); len=makeerr(Cannot_create_file,send_buffer); ret=sendto(sock,send_buffer,len,0,(structsockaddr*)&dest_addr,sizeof(dest_addr)); record(5,&sour_addr,filename); return; } //发送ACK len=makeack(blocknum,send_buffer,sizeof(send_buffer)); ret=sendto(sock,send_buffer,len,0,(structsockaddr*)&dest_addr,sizeof(dest_addr)); blocknum++; while (1){ FD_ZERO(&fdr); FD_SET(sock,&fdr); ret=select(sock+1,&fdr,NULL,NULL,&timeout); if(-1==ret) { printf("Socket错误\n"); fclose(file); record(5,&sour_addr,filename); return; } else { if(0==ret) { printf("超时\n"); fclose(file); record(5,&sour_addr,filename); return; } else { if(FD_ISSET(sock,&fdr)) { //接收数据包 sour_len=sizeof(structsockaddr); ret=recvfrom(sock,recv_buffer,sizeof(recv_buffer),0,(structsockaddr*)&sour_addr,&sour_len); //如果是数据包 if(TFTP_DATA==recv_buffer[1]) { lastdata=MAKEWORD(recv_buffer[3],recv_buffer[2]);//块号 //如果块号正确 if(lastdata==blocknum) { //发送ACK包 len=makeack(blocknum,send_buffer,sizeof(send_buffer)); sendto(sock,send_buffer,len,0,(structsockaddr*)&dest_addr,sizeof(dest_addr)); blocknum++; if(blocknum>65535) blocknum=0; //最后一包 if(ret { //写入文件 fwrite(&recv_buffer[4],1,ret-4,file); flen=flen+ret-4; #ifdef_DEBUG_ printf("%s%s%d\n",__FILE__,__FUNCTION__,__LINE__); printf("*****传输结束,共收到%d字节*****\n",flen); #endif rewind(file); if((decrypt_file=fopen("decrypt_temp","wb+"))==NULL){ printf("decryptfileopenerror\n"); return; } decrypt(file,decrypt_file); fclose(decrypt_file); rename("decrypt_temp",filename); fclose(file); record(2,&sour_addr,filename); return; } else { fwrite(&recv_buffer[4],1,512,file); flen=flen+512; #ifdef_DEBUG_ printf("%s%s%d\n",__FILE__,__FUNCTION__,__LINE__); printf("已收到%d字节\n",flen); #endif } } else { //重新发送ACK包 printf("数据包块号错误.\n"); sendto(sock,send_buffer,len,0,(structsockaddr*)&dest_addr,sizeof(dest_addr)); } } } } } } } C)客户端与服务都配有工程管理器,可通过make完成编译。 D)实现效果: 以上内容就是教大家如何基于c语言tftp服务器与客户端实现,是否获益匪浅呢? 更多内容可以在华清远见官网查询,华清远见提供免费的资料供大家参考和学习。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 如何 基于 语言 tftp 服务器 客户端 实现
![提示](https://static.bdocx.com/images/bang_tan.gif)