模拟tftp客户端

发布于:2023-01-04 ⋅ 阅读:(360) ⋅ 点赞:(0)

目录

1.要实现的功能

2.流程图

3.步骤

1.请求链接,监听

2.搭建号服务器后具体操作

3.解析字符串的函数

4.数据处理函数

5.上传下载



要实现的功能

客户端                                                                                                服务器端

我们规定在输入指令以后要加上一个'#'                                        1.监听是否有人链接

发送指令 “put 1.txt#”    上传文件                                                  2.接受链接

"get 1.txt#"                   下载文件                                                  3.接受指令“put 1.txt#”

"quit#"                          退出                                                                            “get 1.txt#”

1.解析空格之前的是命令 char cmd[20]="get"                                      1.解析你recv的字符串            2.解析空格之后#之前      char filename[20]="1.txt"                              2.解析空格之后#之前

3.通过strcmp来判断输入的命令是否正确                                               if(strcmp(cmd,"put"))

if(strcmp(cmd,"put"))                                                                                   1.接收文件大小

1.获得文件的大小        int len ==stat() 12340                                              2.解析12340

2.将文件大小传送过去 "filesize=12340#"                                                3.接受文件内容并保存

3.将文件的内容发送过来                                                              //1.从socket当中读取数据到buf中

        //1.先将文件的内容读取给buf                                                //2.将buf中的数据写到文件中

        //2.将buf通过socket发送过去

2.流程图

客户端

开始->请求链接->输入buf->send服务器->buf==“quit” //-y>关闭socket对象//-n>buf中解析出cmd,filename->cmd==“put”//-y>上传文件//-n>cmd="get"//-y>下载文件//-n>error

服务器

开始->监听是否有人链接->接受链接生成newfd->recv客户端给buff->buf==“quit” //-y>关闭socket对象//-n>buf中解析出cmd,filename->cmd==“put”//-y>下载文件//-n>cmd="get"//-y>上传文件//-n>error

3.步骤

1.请求链接,监听

//一.请求链接
int tcp_connect(const char *ip,int port)
{
//创建socket对象(流式套接字TCP)
int socket_fd = socket(AF_INET,SOCK_STREAM,0);//参数是地址组,套接字类型,第三个通常置为0
if(sicket_fd < 0)
{
    perror("socket error");
    return -1;
}
printf("socket success\n");
//设置对方的ip地址和端口号
//定义一个结构体并为其赋值
struct sockaddr_in server;
memset(&server,'\0',sizeof(server));//清空结构体
server.sin_family =AF_INET; //ipv4协议
server.sin_port = htons(port);//端口号
server.sin_addr.s_addr = inet_addr(ip);//网络字节序
//请求链接
if(connect(socket_fd,(struct sockaddr *)&server,sizeof(server))<0)
{
    perror("connect error\n");
    return -1;
}
printf("connect success\n");
return socket_fd;
}
监听
int tcp_socket(const char *ip, int port)
{
	//创建socket
	int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == socket_fd)
	{
		perror("create socket error");
		return -1;
	}
	printf("socket创建成功\n");

	//指定端口及ip地址
	struct sockaddr_in server;
	memset(&server,'\0',sizeof(server));

	server.sin_family = AF_INET;
	server.sin_port = htons(port);
	server.sin_addr.s_addr = inet_addr(ip);

	//绑定ip地址及端口
	if(bind(socket_fd,(struct sockaddr *)&server,sizeof(server)) < 0)
	{
		perror("bind error");
		return -1;
	}
	printf("bind ok\n");

	//监听是否有人连接
	if(listen(socket_fd,5) < 0)
	{
		perror("listen error");
		return -1;
	}
	printf("listen ok\n");

	return socket_fd;
}

2.搭建号服务器后具体操作

客户端

int main(int argc, const char *argv[])
{
//入参判断
if(argc<3)
{
    perror("argc error");
    return -1;
}
//连接服务器返回链接后的socket对象
int fd = tcp_connect(argv[1],atoi(argv[2]));//atoi是把字符转成整形
//buf中输入值
char buf[100] = {0};
char cmd[100] = {0};
char filename[100] = {0};
fgets(buf,sizeof(buf),stdin);//键盘键入
send(fd,buf,strlen(buf),0);//发送到服务器
parseStr(buf,cmd,filename);//解析键入的字符串
if(strncmp(cmd,"quit",4)==0)break;
printf("cmd=%s",cmd);
printf("fliename=%s",filename);
DataHandler(fd,cmd,filename);//数据处理(上传下载文件)
//关闭socket
close(fd);
return 0;
}

服务器

int main(int argc, const char *argv[])
{
//入参判断
if(argc<3)
{
    perror("argc error");
    return -1;
}
//连接服务器返回链接后的socket对象
int newfd = tcp_tocket(argv[1],atoi(argv[2]));//atoi是把字符转成整形
//buf中输入值
char buf[100] = {0};
char cmd[100] = {0};
char filename[100] = {0};
recv(newfd,buf,sizeof(buf),0);//接收
parseStr(buf,cmd,filename);//解析命令和文件名
if(strncmp(buf,"quit",4)==0)
break;
printf("cmd=%s",cmd);
printf("filename=%s",filename);
DataHandler(newfd,cmd,filename);//数据处理函数
//关闭socket
close(newfd);
return 0;
}

3.解析字符串的函数

//编写一个子函数,根据输入的字符串进行解析命令和文件名
void parseStr(char buf[],char cmd[],char filename[])
{
// 解析命令
int i = 0;
while(buf[i]!='#')
{
    if(buf[i]==' ')
    break;
cmd[i]=buf[i];
i++;
}
cmd[i]='\0';
//解析文件名
if(buf[i]!=' ')//防止有别的符号
return;
i++;//把空格跳过去
int j=0;
while(buf[i+j]!='#')
{
    filename[j]=buf[i+j];
    j++;
}
filename[j]='\0';
}

4.数据处理函数

客户端
int DataHandler(int fd,char * cmd,char * filename)
{
    if(strncmp(cmd,"put",3)==0)
{
    //上传文件
    upload(fd,filename);
}
else if(strncmp(cmd,"get",3)==0)
{
    //下载文件
    download(fd,filename);
}
else
{
    printf("命令有误\n");
}
}
服务器
int DataHandler(int fd,char * cmd,char * filename)
{
    if(strncmp(cmd,"get",3)==0)
{
    //下载文件
    download(fd,filename);
}
else if(strncmp(cmd,"get",3)==0)
{
    //上传文件
    upload(fd,filename);
}
else
{
    printf("命令有误\n");
}
}

5.上传下载

//上传
int upload(int fd,char * filename)
{
    //获得文件的大小
    struct stat statbuf;
    if(stat(filename,&statbuf)<0)
    {
        perror("stat error");
        return -1;
    }
    printf("filesize=%d\n",statbuf.st_size);
    //2.将文件大小发送过去
    char filesize[20]={'\0'};
    sprintf(filesize,"%d#",statbuf.st_size);
    int n=send(fd,filesize,strlen(filesize),0);
    printf("filesize=%s n=%d\n",filesize,n);
    
    sleep(1);

    //以只读方式打开文件
    int fr=open(filename,O_RDONLY);
    if(fr<0)
    {
        perror("open error");
        return -1;
    }
    char bufstr[1024]={'\0'};
    while(1)
    {
        memset(bufstr,'\0',sizeof(bufstr));
        //从文件中读取数据到bufstr
        int n=read(fr,bufstr,sizeof(bufstr));
        if(n==0)
        {
            printf("文件上传成功\n");
            break;
        }
        //将bufstr写入到socket中
        send(fd,bufstr,n,0);
    }
    //关闭文件
    close(fr);
}
//下载
int download(int fd,char * filename)
{
    //接收文件大小
    char buf[20]={'\0'};
    recv(fd,buf,sizeof(buf),0);
    //将字符串转换成整数
    int filesize=atoi(buf);
    printf("filesize=%d\n",filesize);
    //以只写的方式打开文件,文件不存在则新建,文件存在则清空文件中的内容
    int fw=0;
    fw=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0777);
    if(fw<0)
    {
        perror("open error");
        return -1;
    }
    int total = 0;
    char bufstr[1024]={'\0'};
    while(1)
    {
    if(total>=filesize)
    {
        printf("文件保存成功\n");
        break;
    }
    //从socket中读取数据
    int n=recv(fd,bufstr,sizeof(bufstr),0);
    total+=n;
    //将读取到的数据写入到文件中
    write(fw,bufstr,n);
    }
close(fw);
}

本文含有隐藏内容,请 开通VIP 后查看