1.代码
#include <head.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"line: %d\n",__LINE__);\
perror(msg);\
return -1;\
}while(0);
#define IP "192.168.8.249"
//#define IP "192.168.74.186"
//#define IP "192.168.0.226"
#define PORT 69
//文件的打开
int file(char *filename);
int file1(char *filename);
void mume();
int main(int argc,const char * argv[])
{
//创建报式字节套
int sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0){
ERR_MSG("socket");
return -1;
}
//先写给客户端找到所谓的连接
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
socklen_t len = sizeof(sin);
//把tftp的临时端口信息留在新的结构体中
struct sockaddr_in cin;
socklen_t len1 = sizeof(cin);
char buf[128] = "";
char str[128] = "";
char filename[30] = "";
int res = 0;
int res1 = 0;
//文件名
int fd = -1;
char buff[800] = "";
unsigned short st = 0;
unsigned short st1 = 0;
int sum = 0;
while(1){
mume();
printf("选择(输入0,1,2)--->");
scanf("%d",&sum);
switch(sum){
case 0://退出
close(fd);
close(sfd);
printf("退出成功\n");
return 0;
case 1://下载
{
TEXT:
memset(filename,0,sizeof(filename));
printf("请输入需要下载的文件名\n");
scanf("%s",filename);
// strcpy(rw.buf,buf);
// 文件名传入服务器上
res = sprintf(buff,"%c%c%s%c%s%c",0,1,filename,0,"octet",0);
if(res < 0){
ERR_MSG("sprintf");
return -1;
}
//发送文件给服务器收到信息
res = sendto(sfd,buff,res,0,(struct sockaddr*)&sin,len);
if(res < 0){
ERR_MSG("sendto");
return -1;
}
//下载
while(1){
//接收信息并判断是否为正确的信息并退出且保存在目录下
//读第一次的数据
memset(buff,0,sizeof(buff));
res1 = recvfrom(sfd,buff,sizeof(buff),0,(struct sockaddr*)&cin,&len1);
if(res < 0){
ERR_MSG("recvfrom");
return -1;
}
//第一次的数据包的解析如果是错误的就之间回头写文件名
if(5 == *((char*)buff+1)){
if(1 == ntohs(*((unsigned short*)buff+1))){
printf("错误码是[%d] 错误信息是[%s]",(*((char*)buff+1)),(char*)(buff+4));
printf("请重新输入文件名\n");
goto TEXT;
}
printf("错误码是[%d] 错误信息是[%s]",(ntohs(*((unsigned short*)buff+1))),(char*)(buff+4));
return -1;
}
//可以执行到这就是正确的文件
//在这步打开文件并写入
if(1 == ntohs(*((unsigned short*)buff+1))){
fd = file(filename);
}
// printf("buff = %ld\n",strlen(buff));
//写入到文件中
//到达这里就是需要给对面回复ACK和保存在本目录下
write(fd,(char*)(buff+4),res1-4);
//如果小于516bt就相当于文件传输结束
//回复ACK
buff[1] = 4;
res = sendto(sfd,buff,4,0,(struct sockaddr*)&cin,len1);
if(res < 0){
ERR_MSG("sendto");
return -1;
}
if( 1 != ntohs(*((unsigned short*)buff+1))){
if(res1 < 516){
printf("文件下载完成\n");
break;
}
}
}
}
break;
case 2://上传
{
TEXT1:
memset(filename,0,sizeof(filename));
printf("请输入需要上传的文件名\n");
scanf("%s",filename);
// strcpy(rw.buf,buf);
// 文件名传入服务器上判断是否存在存在重新输入
res = sprintf(buff,"%c%c%s%c%s%c",0,2,filename,0,"octet",0);
if(res < 0){
ERR_MSG("sprintf");
return -1;
}
// printf("%s __%d__\n",buff,__LINE__);
//发送文件给服务器收到信息
res = sendto(sfd,buff,res,0,(struct sockaddr*)&sin,len);
if(res < 0){
ERR_MSG("sendto");
return -1;
}
//上传
while(1){
//收ack如果第一次收到时是正确的码那就读并上传
memset(buff,0,sizeof(buff));
res1 = recvfrom(sfd,buff,sizeof(buff),0,(struct sockaddr*)&cin,&len1);
if(res1 < 0){
ERR_MSG("recvfrom");
return -1;
}
//printf("%d __%d__\n",ntohs(*(short*)buff),__LINE__);
//第一次的ACK的解析如果是错误且文件存在的就之间回头写文件名
if(5 == ntohs(*(short*)buff)){
if(6 == ntohs(*((unsigned short*)buff+1))){
printf("错误码是[%d] 错误信息是[%s]",(*((char*)buff+1)),(char*)(buff+4));
printf("文件已经存在,请重新输入文件名\n");
goto TEXT1;
}
printf("错误码是[%d] 错误信息是[%s]",(ntohs(*((unsigned short*)buff+1))),(char*)(buff+4));
return -1;
}
//如果收到APK后是对的且上次读到的数据比516少就退出
if( 0 != ntohs(*((unsigned short*)buff+1))){
if(res < 516){
printf("文件上传完成\n");
break;
}
}
//可以执行到这就是正确的需要上传的文件
//在这步打开文件并读取
if(0 == ntohs(*((unsigned short*)buff+1))){
fd = file1(filename);
if(fd < 0||0 == fd){
printf("需要上传的文件不存在\n");
goto TEXT1;
}
}
// printf("buff = %ld\n",strlen(buff));
//写入到文件中
//到达这里就是需要给对面回复ACK和保存在本目录下
res = read(fd,(char*)(buff+4),512);
if(res < 0){
ERR_MSG("read");
return -1;
}
//printf("%d __%d__\n",res,__LINE__);
//printf("%s\n",(char*)buff+4);
//如果小于516bt就相当于文件传输结束
//传递数据包
buff[1] = 3;
buff[3] = buff[3] +1;
res = sendto(sfd,buff,res+4,0,(struct sockaddr*)&cin,len1);
if(res < 0){
ERR_MSG("sendto");
return -1;
}
}
}
break;
}
getchar();
printf("<-----请输入enter键清除该页面----->\n");
getchar();
}
return 0;
}
//打开文件
int file(char *filename){
int fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
if(fd < 0){
ERR_MSG("open");
return -1;
}
return fd;
}
int file1(char *filename){
int fd = open(filename,O_RDONLY);
return fd;
}
void mume(){
system("clear");
printf("--------------------------------------\n");
printf("--------------------------------------\n");
printf("--------------0.退出------------------\n");
printf("--------------1.下载------------------\n");
printf("--------------2.上传------------------\n");
printf("--------------------------------------\n");
printf("--------------------------------------\n");
}
下载
上传
退出