tftp--实现服务器与客户端的下载与上传【转】
转自:https://blog.csdn.net/xiaopangzi313/article/details/9122975
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaopangzi313/article/details/9122975
项目功能:实现服务器与客户端的下载与上传,及linux系统下的tftp功能
项目名称:tftp--实现服务器与客户端的下载与上传
开发环境:linux /C
开发工具:GCC/GDB
网络协议:TCP/IP
补充说明:程序中默认server端有upload文件夹用以接收client端上传的数据,client端有download文件夹用以下载server端的文件
开发流程:
编译流程:
1.cc server.c -o server
2.cc client.c -o client
运行l流程:
1. ./server 192.168.1.207(server ip) 8888(port)
2. ./client 192.168.1.207 8888
调试效果:
client 端
server 端
1.server.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<signal.h>
#include<errno.h>
#include <dirent.h>
typedef struct {
char cmd[10];
int size;
char buf[1024];
}MSG;
MSG msg;
enum{list,get,put};
int do_list(int connect_fd)
{
char buf[1024];
int n;
int fd;
DIR *pdir;
struct dirent *pdirent;
if((pdir = opendir(".")) == NULL)
{
perror("Fail to open directory ");
exit(EXIT_FAILURE);
}
while((pdirent = readdir(pdir)) != NULL)
{
if(pdirent->d_name[0] == '.' )
continue;
strcpy(msg.buf,pdirent->d_name);
msg.size = strlen(msg.buf);
msg.size = send(connect_fd,&msg,sizeof(MSG),0);
}
msg.size = 0;
send(connect_fd,&msg,sizeof(MSG),0);
puts("send list successfully");
return 0;
}
int do_get(int connect_fd)
{
char filename[10];
int n;
int fd;
struct stat fileinfo;
if(recv(connect_fd,&msg,sizeof(MSG),0) < 0)
{
perror("fail to recv");
exit(EXIT_FAILURE);
}
if(stat(msg.buf,&fileinfo) < 0)
{
perror("fail to stat");
msg.size = -1;
strcpy(msg.buf,strerror(errno));
send(connect_fd,&msg,sizeof(MSG),0);
return -1;
}
msg.size = fileinfo.st_size;
strcpy(filename,msg.buf);
puts("***********************");
printf("send file size : %d\n",msg.size);
printf("send filename : %s\n",msg.buf);
puts("***********************");
if(send(connect_fd,&msg,sizeof(MSG),0) < 0)
{
perror("fail to recv");
exit(EXIT_FAILURE);
}
if((fd = open(msg.buf,O_RDONLY)) < 0)
{
fprintf(stderr,"Fail to open %s, %s\n",msg.buf,strerror(errno));
exit(EXIT_FAILURE);
}
while(1)
{
msg.size = read(fd, msg.buf,sizeof(msg.buf));
send(connect_fd,&msg,sizeof(MSG),0);
if(msg.size == 0)
break;
}
printf("send file %s successfully\n",filename);
return 0;
}
int do_put(int connect_fd)
{
char buf[1024];
int n;
int fd;
if(recv(connect_fd,&msg,sizeof(msg),0) <= 0)
{
perror("fail to recv");
exit(EXIT_FAILURE);
}
puts("**********************************");
printf("upload filename : %s\n",msg.buf);
printf("size: %d\n",msg.size);
puts("**********************************");
strcpy(buf,"./upload/");
strcat(buf,msg.buf);
if((fd = open(buf,O_WRONLY | O_CREAT | O_TRUNC,0666)) < 0)
{
perror("Fail to accept");
exit(EXIT_FAILURE);
}
ftruncate(fd,msg.size);
while(1)
{
recv(connect_fd,&msg,sizeof(MSG),0);
write(fd,msg.buf,msg.size);
if(msg.size == 0)
break;
}
printf("send file successfully!\n");
exit(EXIT_SUCCESS);
}
int getcmd(char *pcmd)
{
if(strcmp(pcmd,"list") == 0)
return 0;
if(strcmp(pcmd,"get") == 0)
return 1;
if(strcmp(pcmd,"put") == 0)
return 2;
}
void do_task(int connect_fd,char *cmd)
{
MSG msg;
switch(getcmd(cmd))
{
case put:
printf("recv file from client...\n");
do_put(connect_fd);
break;
case get:
printf("send file to client...\n");
do_get(connect_fd);
break;
case list:
printf("send file list to client...\n");
do_list(connect_fd);
break;
default :
break;
}
return;
}
int do_client(int connect_fd)
{
MSG msg;
int n;
while(1)
{
if((n =recv(connect_fd,&msg,sizeof(msg),0) )< 0)
{
perror("fail to recv");
exit(EXIT_FAILURE);
}
if(n == 0)
break;
do_task(connect_fd,msg.cmd);
}
exit(EXIT_FAILURE);
}
void signal_handler(int signum)
{
waitpid(-1,NULL,WNOHANG);
return;
}
int main(int argc, const char *argv[])
{
pid_t pid;
int listen_fd;
int connect_fd;
socklen_t addrlen;
struct sockaddr_in peer_addr;
struct sockaddr_in server_addr;
if(argc < 0)
{
perror("fail to argc");
exit(EXIT_FAILURE);
}
if(signal(SIGCHLD,signal_handler) == SIG_ERR)
{
perror("fail to signal");
exit(EXIT_FAILURE);
}
if((listen_fd = socket(AF_INET,SOCK_STREAM,0) )< 0)
{
perror("fail to socket");
exit(EXIT_FAILURE);
}
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr =inet_addr(argv[1]);
if(bind(listen_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0) //描述本机端口和IP,要知道数据包发往哪个进程
{
perror("Fail to bind");
exit(EXIT_FAILURE);
}
if(listen(listen_fd,8 ) < 0)//监听连接的套接字,接收各客户端的请求,返回监听套接字文件描述符
{
perror("Fail to listen");
exit(EXIT_FAILURE);
}
puts("listening ...");
addrlen = sizeof(peer_addr);
while(1)
{
if((connect_fd = accept(listen_fd,(struct sockaddr *)&peer_addr,&addrlen)) < 0)
{
perror("Fail to accept");//提取客户发过来的请求,返回新的已连接的套接字文件描述符
exit(EXIT_FAILURE);
}
puts("*************************");
printf("IP : %s\n",inet_ntoa(peer_addr.sin_addr));
printf("PORT : %d\n",ntohs(peer_addr.sin_port));
puts("*************************");
if((pid = fork()) < 0)
{
perror("Fail to listen");
exit(EXIT_FAILURE);
}
if(pid == 0)
{
do_client(connect_fd);
}
close(connect_fd);
}
exit(EXIT_FAILURE);
}
2.client.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<errno.h>
typedef struct {
char cmd[10];
int size;
char buf[1024];
}MSG;
enum{list,get,put};
int do_list(client_fd,pname)
{
MSG msg;
int fd;
while(1)
{
recv(client_fd,&msg,sizeof(MSG),0);
if(msg.size == 0)
break;
printf("%s\n",msg.buf);
}
puts("get list successfully");
return 0;
}
int do_get(int client_fd,char *filename)
{
MSG msg;
int fd;
char buf[1024];
strcpy(msg.buf,filename);
if(send (client_fd,&msg,sizeof(MSG),0) < 0)
{
perror("Fail to send");
exit(EXIT_FAILURE);
}
recv(client_fd,&msg,sizeof(MSG),0);
if(msg.size < 0)
{
printf("Error :%s \n",msg.buf);
return -1;
}
puts("***********************");
printf(" download file size : %d\n",msg.size);
printf(" download filename : %s\n",msg.buf);
puts("***********************");
strcpy(buf,"./download/");
strcat(buf,msg.buf);
if((fd = open(buf,O_WRONLY | O_CREAT | O_TRUNC,0666)) < 0)
{
fprintf(stderr,"Fail to open %s,%s\n",buf,strerror(errno));
exit(EXIT_FAILURE);
}
ftruncate(fd, msg.size);
while(1)
{
recv(client_fd,&msg,sizeof(MSG),0);
if(msg.size == 0)
break;
write(fd,msg.buf,msg.size);
}
printf("download file %s successfully\n",filename);
return 0;
}
int do_put(int client_fd,char *filename)
{
MSG msg;
int fd;
int n;
if((fd = open(filename,O_RDONLY)) < 0)
{
perror("Fail to open");
exit(EXIT_FAILURE);
}
msg.size = lseek(fd,0,SEEK_END);
strcpy(msg.buf,filename);
lseek(fd,0,SEEK_SET);
puts("**********************************");
printf("filename : %s\n",msg.buf);
printf("size :%d\n",msg.size);
puts("**********************************");
if(send(client_fd,&msg,sizeof(MSG),0) < 0)
{
perror("Fail to send");
exit(EXIT_FAILURE);
}
while(1)
{
msg.size = read(fd,msg.buf,sizeof(msg.buf));
if(send(client_fd,&msg,sizeof(MSG),0) < 0)
{
perror("Fail to read");
exit(EXIT_FAILURE);
}
if(msg.size == 0)
break;
}
printf("upload file successfully!\n");
return 0;
}
int getcmd(char *pcmd)
{
if(strcmp(pcmd,"list") == 0)
return 0;
if(strcmp(pcmd,"get") == 0)
return 1;
if(strcmp(pcmd,"put") == 0)
return 2;
}
int do_task(char *pcmd,char *pname,int client_fd)
{
MSG msg;
char buf[1024];
int fd;
switch(getcmd(pcmd))
{
case list:
printf("get file list from the server ...\n");
strcpy(msg.cmd,pcmd);
if(send(client_fd,&msg,sizeof(MSG),0) < 0)
{
perror("FAIL to send");
exit(EXIT_FAILURE);
}
do_list(client_fd,pname);
break;
case get:
printf("file %s is downloading from server ...\n",pname);
strcpy(msg.cmd , pcmd);
if(send(client_fd,&msg,sizeof(MSG),0) < 0)
{
perror("FAIL to send");
exit(EXIT_FAILURE);
}
do_get(client_fd,pname);
break;
case put:
printf(" file %s is uploading to server ...\n",pname);
strcpy(msg.cmd,pcmd);
if(send(client_fd,&msg,sizeof(MSG),0) < 0)
{
perror("Fail to send!");
exit(EXIT_FAILURE);
}
do_put(client_fd,pname);
break;
default:
break;
}
return 0;
}
int main(int argc, const char *argv[])
{
MSG msg;
char buf[1024];
char *pname,*pcmd;
int client_fd;
pid_t pid;
int connect_fd;
socklen_t addrlen;
struct sockaddr_in server_addr;
if((client_fd = socket(AF_INET,SOCK_STREAM,0) )< 0)
{
perror("fail to socket");
exit(EXIT_FAILURE);
}
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr =inet_addr(argv[1]);
server_addr.sin_port = htons(atoi(argv[2]));
if(connect(client_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
{
perror("Fail to accept");
exit(EXIT_FAILURE);
}
while(1)
{
printf("tftp>");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf) -1] = '\0';
if(strncmp(buf,"quit",4) == 0)
break;
pcmd = strtok(buf," ");
pname = strtok(NULL," ");
do_task(pcmd,pname,client_fd);
}
exit(EXIT_FAILURE);
return 0;
}
---------------------
作者:xiaopangzi313
来源:CSDN
原文:https://blog.csdn.net/xiaopangzi313/article/details/9122975
版权声明:本文为博主原创文章,转载请附上博文链接!
tftp--实现服务器与客户端的下载与上传【转】的更多相关文章
- 网络编程 UDP协议 TCP局域网客户端与服务端上传下载电影示例
UDP协议 (了解) 称之为数据包协议,又称不可靠协议. 特点: 1) 不需要建立链接. 2) 不需要知道对方是否收到. 3) 数据不安全 4) 传输速度快 5)能支持并发 6) 不会粘包 7) 无需 ...
- 编写Java程序,实现客户端向服务端上传文件的功能
查看本章节 查看作业目录 需求说明: 实现客户端向服务端上传文件的功能 当启动服务端后,运行客户端程序,系统提示客户在客户端输入上传文件的完整路径.当客户在客户端输入完成后,服务端实现文件上传 实现思 ...
- iOS开发——网络篇——NSURLSession,下载、上传代理方法,利用NSURLSession断点下载,AFN基本使用,网络检测,NSURLConnection补充
一.NSURLConnection补充 前面提到的NSURLConnection有些知识点需要补充 NSURLConnectionDataDelegate的代理方法有一下几个 - (void)conn ...
- ios开发之网络数据的下载与上传
要实现网络数据的下载与上传,主要有三种方式 > NSURLConnection 针对少量数据,使用“GET”或“POST”方法从服务器获取数据,使用“POST”方法向服务器传输数据; > ...
- 重新想象 Windows 8.1 Store Apps (89) - 通信的新特性: 下载数据, 上传数据, 上传文件
[源码下载] 重新想象 Windows 8.1 Store Apps (89) - 通信的新特性: 下载数据, 上传数据, 上传文件 作者:webabcd 介绍重新想象 Windows 8.1 Sto ...
- iOS开发——网络Swift篇&NSURLSession加载数据、下载、上传文件
NSURLSession加载数据.下载.上传文件 NSURLSession类支持三种类型的任务:加载数据.下载和上传.下面通过样例分别进行介绍. 1,使用Data Task加载数据 使用全局的 ...
- [转载]ASP.NET Core文件上传与下载(多种上传方式)
ASP.NET Core文件上传与下载(多种上传方式) 前言 前段时间项目上线,实在太忙,最近终于开始可以研究研究ASP.NET Core了. 打算写个系列,但是还没想好目录,今天先来一篇,后面在 ...
- Android开发 retrofit下载与上传
前言 此博客只讲解retrofit下载与上传的使用,其实与其说是retrofit的下载与上传还不如说,依然是Okhttp的下载与上传.如果你需要了解retrofit入门请查看这篇博客(此博客不在详细讲 ...
- SVN服务器和客户端的下载和安装
一.SVN服务器VisualSVN下载和安装 当前版本:4.1.3下载地址:https://www.visualsvn.com/server/download/下载下来的文件:VisualSVN-Se ...
随机推荐
- Linux centos 推拉、共享、监控的设置的分享
新建四台虚拟机 打开第一台连接shell更改主机名.网卡 backup 1.主机名网卡配置 [root@jytcentos7.6 ~]# hostnamectl set-hostname backup ...
- 2018年NGINX最新版高级视频教程
2018年NGINX最新版高级视频教程,想要的联系我,QQ:1844912514
- CountDownLatch、CyclicBarrier和Semaphore基本原理和使用
一.CountDownLatch CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能. 比如有一个任务A,它要等待其他4个任务执行完毕之后才 ...
- 代码管理git 工具的话可以使用GitHub桌面端管理git、码云上的代码
git版本控制 廖雪峰老师的git教程 git是linus 1991年创建了开源的linux...已成为最大的服务器系统软件 集中式的版本控制器:CVS.SVN.ClearCase是IBM的收费软件 ...
- bugku web 管理员系统
页面是一个登陆表单,需要账号密码,首先f12查看源代码,发现有一段可疑的注释,明显是base64,解码得到test123,似乎是一个类似于密码的东西,既然是管理员,就猜测用户名是admin,填上去试一 ...
- 存储类&作用域&生命周期&链接属性
链接属性 (1)大家知道程序从源代码到最终可执行程序,经历的过程:编译.链接. (2)编译阶段就是把源代码搞成.o目标文件,目标文件里面有很多符号和代码段.数据段.bss段等分段.符号就是编程中的变量 ...
- Spring MVC 使用介绍(十三)数据验证 (一)基本介绍
一.消息处理功能 Spring提供MessageSource接口用于提供消息处理功能: public interface MessageSource { String getMessage(Strin ...
- subprocess
在没有subprocess这个模块的时候,我们怎么去跟我们的操作系统做交互的呐?下面我们先说说这三个模块:os.system().os.popen().commands. 1. os.system( ...
- [leetcode] 5.Longest Palindromic Substring-1
开始觉得挺简单的 写完发现这个时间超限了: class Solution: def longestPalindrome(self, s: str) -> str: # longest palin ...
- Spring Boot整合Elasticsearch
Spring Boot整合Elasticsearch Elasticsearch是一个全文搜索引擎,专门用于处理大型数据集.根据描述,自然而然使用它来存储和搜索应用程序日志.与Logstash和K ...