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 ...
随机推荐
- PyCharm选中文件夹新建时Directory与Python package的区别
pycharm创建普通的directory和package时都是在硬盘上建立一个文件夹.但是建package时会在这个文件夹中自动地生成一个空的__init__.py文件.python的一个包是一个带 ...
- 【算法】C语言趣味程序设计编程百例精解
C语言趣味程序设计编程百例精解 C/C++语言经典.实用.趣味程序设计编程百例精解(1) https://wenku.baidu.com/view/b9f683c08bd63186bcebbc3c. ...
- Kafka简介及使用PHP处理Kafka消息
Kafka简介及使用PHP处理Kafka消息 Kafka 是一种高吞吐的分布式消息系统,能够替代传统的消息队列用于解耦合数据处理,缓存未处理消息等,同时具有更高的吞吐率,支持分区.多副本.冗余,因此被 ...
- nginx 返回json格式内容
例子: #如果访问的ip是192.168.1.1,就直接返回json格式的内容 location / { default_type application/json; #####格式 if ( $re ...
- syntax error near unexpected token `$'\r''
这种情况发生的原因是因为你所处理的文件换行符是dos格式的"\r\n"可以使用cat -v 文件名 来查看换行符是否是,如果是上述的,则行结尾会是^m需要转换成linux/unix ...
- Java中的String,StringBuilder,StringBuffer
String被final修饰,不可变,每次更改其实是重新创建了一个对象.StringBuilder,StringBuffer是可变的. StringBuffer是线程安全的,StringBuilder ...
- DNS预解析prefetch
前面的话 本文将详细介绍DNS预解析prefetch的主要内容 概述 DNS(Domain Name System, 域名系统),是域名和IP地址相互映射的一个分布式数据库.DNS 查询就是将域名转换 ...
- oracle wm_concat 函数无法使用的情况下,使用LISTAGG()函数
http://dacoolbaby.iteye.com/blog/1698957 --20180327 重写wm_concat函数,解决行数超过上限问题 /*执行前请将APPS替换为当前登录用户*/ ...
- 牛客小白月赛13 小A买彩票 (记忆化搜索)
链接:https://ac.nowcoder.com/acm/contest/549/C来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言52428 ...
- luogu5283 异或粽子
题目链接 思路 首先求个前缀异或和,这样就可以\(O(1)\)的得到区间异或和了. 然后发现问题转化为 找出不同的\(k\)个二元组\(x,y\).使得\(a_x \otimes a_y\)的和最大. ...