linux下基于tcp的FTP编程
来源:互联网 发布:如何清理地图数据 编辑:程序博客网 时间:2024/06/08 19:09
客户端输入:
ls : 显示本地文件列表
service ls: 显示服务器文件列表
upload xxx: 实现xxx文件读取与上传
download xxx : 实现xxx文件下载与存储
公共函数commonfunc.c 代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "commonfunc.h"
#include <stddef.h>
#include <dirent.h>
#define BACKLOG 10//最大连接数
/******************函数作用:网络初始化*****************/
int network_init(int net_type, const char* NET_IP, short NET_NUM)
{
int sockfd;
if(-1 == (sockfd = socket(PF_INET, SOCK_STREAM, 0))) //创建监听套接字
{
perror("Create socket error!");
//exit(EXIT_FAILURE);
return -1;
}
struct sockaddr_in sockadd;
memset(&sockadd, 0, sizeof(sockadd));
sockadd.sin_family = AF_INET;
sockadd.sin_port = htons(NET_NUM);
sockadd.sin_addr.s_addr = inet_addr(NET_IP);
if(NET_CLIENT == net_type)
{
//连接服务器
if(-1 == connect(sockfd, (struct sockaddr*)(&sockadd),\
sizeof(sockadd)))
{
perror("Connect error!");
//exit(EXIT_FAILURE);
return -1;
}
}
else
{
if(NET_SERVER == net_type)
{
//绑定IP地址端口号
if(-1 == bind(sockfd, (struct sockaddr*)(&sockadd),\
sizeof(sockadd)))
{
perror("Bind error!");
return -1;
}
if(-1 == listen(sockfd, BACKLOG)) //监听客户端
{
perror("Listen error!");
return -1;
}
}
else
{
return -1;
}
}
return sockfd;
}
/**************************命令解析函数************************/
int ftp_cmd_analyse(const char* cmd)
{
if(NULL == cmd)
{
return CMD_ERROR;
}
else
{
if(0 == strncmp(cmd, "ls",2)) //列出本地文件列表指令
return CMD_LS;
else
{
if(0 == strncmp(cmd, "server ls", 9)) //列出服务器文件列表指令
return CMD_SERVER_LS;
else
{
if(0 == strcmp(cmd, "quit")) //断开链接指令
return CMD_QUIT;
else
{
if(0 == strncmp(cmd, "download ", 9)) //从服务器下载文件指令
return CMD_DOWNLOAD;
else
{
if(0 == strncmp(cmd, "upload ", 7)) //上传文件到服务器指令
return CMD_UPLOAD;
else
{
return CMD_ERROR;
}
}
}
}
}
}
}
/****************从服务器端获取文件列表函数********************/
int ftp_getlist(int getsockfd)
{
char GET_BUFF[BUFF_LEN];
int readsize;
sprintf(GET_BUFF, "server ls");
if(-1 == write(getsockfd, GET_BUFF, BUFF_LEN)) //向服务器发送命令
{
perror("Send cmd error!");
return -1;
}
else
{
while(1) //循环读取
{
readsize = read(getsockfd, GET_BUFF, BUFF_LEN);
if(readsize <= 0) //读错误
{
perror("Get list error!");
return -1;
}
else
{
if(0 == strncmp(GET_BUFF, GET_LIST_END, \
sizeof(GET_LIST_END))) //判断服务器是否发送完毕
{
break; //发送完毕,退出
}
else
{
printf("%s\n", GET_BUFF); //服务器端发送完毕,显示文件
}
}
}
}
return getsockfd;
}
/**************把服务器端文件列表发送到客户端函数**************/
int ftp_putlist(int putsockfd)
{
const char* LIST_NAME=".";
char PUT_BUFF[BUFF_LEN];
int strn, strm;
DIR* dp;
struct dirent *ep;
struct stat st;
char LIST_PATH[256];
dp = opendir(LIST_NAME); //打开目录
if(NULL != dp) //打开目录成功
{
while(ep = readdir(dp)) //循环读目录
{
if(ep->d_name[0] != '.') //如果不是隐藏文件或目录
{
sprintf(PUT_BUFF,"%s",ep->d_name);
write(putsockfd, PUT_BUFF, BUFF_LEN);
}
}
if(-1 == write(putsockfd, GET_LIST_END, BUFF_LEN)) //发送结束
{
perror("Write endstring error!");
return -1;
}
}
else
{
if(-1 == write(putsockfd, GET_LIST_END, BUFF_LEN)) //发送结束
{
perror("Write endstring error!");
return -1;
}
perror("Can't open the directory!");
return -1;
}
closedir(dp);
return putsockfd;
}
/*************************文件接收函数*************************/
int ftp_getfile(int getsockfd, const char* GET_FILENAME)
{
int getfilefd; //存放接收文件的文件描述符
int getfilesize; //实际接收的文件大小
char GET_BUFF[BUFF_LEN]; //接收缓存
//打开一个文件描述符用与保存来自发送端的文件
if(-1 == (getfilefd = open(GET_FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0666)))
{
perror("Can't open or creat file!");
return -1;
}
else
{
while(getfilesize = read(getsockfd, GET_BUFF, BUFF_LEN) > 0) //接收文件
{
if(0 == strncmp(GET_BUFF, "ERROR:", 6)) //接收文件出错
{
printf("%s", GET_BUFF);
return -1;
}
else
{
//取出数据包头中包含的数据区大小
memcpy(&getfilesize, GET_BUFF, 4);
/*GET_BUFF+4是因为数据包前四个字节存放的是数据长度,之后的
1024个字节才存放的实际的数据*/
if(-1 == write(getfilefd, GET_BUFF+4, getfilesize))
{
perror("Download error!"); //接收出错,返回
close(getfilefd); //关闭文件
return -1;
}
if(getfilesize < (BUFF_LEN-4)) //已经读取到文件末尾
break; //接收结束,退出
}
}
close(getfilefd); //关闭文件
return getfilefd; //接收完成,返回接收到的文件的文件描述符。
}
}
/*****************************文件发送函数********************************/
int ftp_putfile(int putsockfd, const char* PUT_FILENAME)
{
int putfilefd; //存放接收文件的文件描述符
int putfilesize; //实际接收的文件大小
char PUT_BUFF[BUFF_LEN];
if(-1 == (putfilefd = open(PUT_FILENAME, O_RDONLY))) //打开文件
{
perror("Open error!");
write(putsockfd, E_NOFILE, BUFF_LEN); //把错误信息写回。
/*如果不写回错误信息,发送端会卡死*/
return -1;
}
else
{
while((putfilesize = read(putfilefd, PUT_BUFF+4, (BUFF_LEN-4))) \
>0)
{
memcpy(PUT_BUFF, &putfilesize, 4);
if(-1 == write(putsockfd, PUT_BUFF, BUFF_LEN))
{
perror("Put file error!");
close(putfilefd);
return -1;
}
memset(PUT_BUFF, 0, BUFF_LEN); //清空缓冲区
}
}
close(putfilefd);
return putfilefd;
}
//////////////////////////////////////////////////公共函数commonfunc.h头文件////////////////////////////////////////////////////
#ifndef __NETWORK_H_
#define __NETWORK_H_
#define NET_SERVER 11
#define NET_CLIENT 22
#define BUFF_LEN 1028//接收发送缓冲区大小
#define CMD_LS 11//列出客户端所有文件
#define CMD_SERVER_LS 22//列出服务器所有文件
#define CMD_DOWNLOAD 33//下载文件
#define CMD_UPLOAD 44//上传文件
#define CMD_QUIT 55//退出
#define CMD_ERROR -1//错误
#define E_NOFILE "ERROR:No such file or directory!\n"
#define E_DODNLOAD "ERROR:Download error!\n"
#define E_UPLOAD "ERROR:Upload error!\n"
#define GET_LIST_END "SUCCESS:GET LIST SUCCESS!"
int network_init(int net_type, const char* IP_ADDRESS, \
short INET_NUM);
void ftp_print_help(void);
int ftp_cmd_analyse(const char* cmd);
int ftp_getlist(int getsockfd);
int ftp_putlist(int putsockfd);
int ftp_getfile(int getsockfd, const char* GET_FILENAME);
int ftp_putfile(int putsockfd, const char* PUT_FILENAME);
#endif
//////////////////////////////////////////////////////////////////////客户端程序///////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "commonfunc.h"
#include <dirent.h>
#define INET_NUM 8888 //端口号
#define IP_ADDRESS "10.104.6.110" //服务器IP
#ifndef BUFF_LEN
#define BUFF_LEN 1028
#endif
#define CMD_LS 11//列出客户端所有文件
#define CMD_SERVER_LS 22//列出服务器所有文件
#define CMD_DOWNLOAD 33//下载文件
#define CMD_UPLOAD 44//上传文件
#define CMD_QUIT 55//退出
#define CMD_ERROR -1//错误
int main(void)
{
int sockfd;
DIR* dp;
struct dirent *ep;
sockfd = network_init(NET_CLIENT, IP_ADDRESS, INET_NUM); //初始化网络连接
if(sockfd == -1)
{
perror("Network init error!");
exit(EXIT_FAILURE);
}
printf("Connect success!\n\n");
printf("*********Operation Help*********\n"); //操作帮助
printf("显示本地文件列表: ls\n");
printf("显示服务器文件列表: server ls\n");
printf("实现xxx文件读取与上传: upload xxx\n");
printf("实现xxx文件下载与存储: download xxx\n");
printf("断开socket链接: quit\n");
printf("*************************************\n\n");
char SEND_BUFF[BUFF_LEN]; //发送数据缓冲区
int cmd_result; //存放命令解析结果
while(1)
{
fgets(SEND_BUFF, sizeof(SEND_BUFF), stdin); //输入命令
SEND_BUFF[strlen(SEND_BUFF)-1] = '\0'; //去掉最后输入的回车符
cmd_result = ftp_cmd_analyse(SEND_BUFF); //解析输入的指令
switch(cmd_result)
{
case CMD_ERROR:
printf("ERROR!\n");
break;
////////////////////////////////////////////////////////////
case CMD_LS: //列出本地文件列表
dp=opendir (".");
printf("*********File List of Client*********\n");
while((ep = readdir(dp)))
{
if(ep->d_name[0] != '.')
{
printf("%s\n",ep->d_name);
}
}
printf("*************************************\n");
printf("List file success!\n");
closedir(dp);
break;
///////////////////////////////////////////////////////////
case CMD_SERVER_LS: //列出服务器端可下载的所有文件
printf("*********File List of Server*********\n");
if(ftp_getlist(sockfd) == -1)
{
printf("List file error!\n");
}
else
{
printf("*************************************\n");
printf("List file success!\n");
}
break;
////////////////////////////////////////////////////////////
case CMD_DOWNLOAD: //从服务器下载文件
if(write(sockfd, SEND_BUFF, BUFF_LEN) == -1)
{
perror("Send cmd error!");
break;
}
if(ftp_getfile(sockfd, SEND_BUFF+9) == -1) //下载文件
{
printf("Download error!\n");
}
else
{
printf("Download The File Success!!\n");
}
break;
////////////////////////////////////////////////////////////
case CMD_UPLOAD: //上传文件到服务器
if(write(sockfd, SEND_BUFF, BUFF_LEN) == -1)
{
perror("Send cmd error!");
break;
}
if(ftp_putfile(sockfd, SEND_BUFF+7) == -1)//上传文件
{
printf("Upload error!\n");
}
else
{
printf("Upload The File Success!!\n");
}
break;
////////////////////////////////////////////////////////////
case CMD_QUIT: //断开连接
printf("Welcome to use again!\nQUIT!\n");
close(sockfd);//客户端关闭文件描述符后就会自动断开连接
exit(EXIT_SUCCESS);
break;
////////////////////////////////////////////////////////////
default:
break;
}
}
close(sockfd);//客户端关闭文件描述符后就会自动断开连接
return 0;
}
//////////////////////////////////////////////////////////////////////服务器程序///////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "commonfunc.h"
#define INET_NUM 8888 //端口号
#define IP_ADDRESS "10.104.6.110" //IP地址
#define BUFF_LEN 1028
#define CMD_LS 11 //列出客户端所有文件
#define CMD_SERVER_LS 22 //列出服务器所有文件
#define CMD_DOWNLOAD 33 //下载文件
#define CMD_UPLOAD 44 //上传文件
#define CMD_QUIT 55 //退出
#define CMD_ERROR -1 //错误
int main(void)
{
int sockfd; //网络套接字
sockfd = network_init(NET_SERVER, IP_ADDRESS, INET_NUM); //初始化网络连接
if(sockfd == -1)
{
perror("Network init error!");
exit(EXIT_FAILURE);
}
printf("LISTEN-ing...\n");
char RCV_BUFF[BUFF_LEN]; //接收缓存
char SEND_BUFF[BUFF_LEN]; //发送缓存
int cmd_result; //命令解析结果
int connectfd; //建立连接后用于通信的套接字文件
int readlen; //读取到的字节数
while(1)
{
if((connectfd = accept(sockfd, NULL, NULL)) == -1) //链接出错,给出提示
{
perror("Connect error!\n");
break;
}
printf("Connect success!\n");
while(1)
{
readlen = read(connectfd, RCV_BUFF, sizeof(RCV_BUFF)); //接收命令
if(readlen <0)//接收出错
{
perror("Read error!\n");
break;
}
else
{
if(readlen == 0) //客户端关闭文件描述符后就会断开连接
{
printf("Welcome to use again!\nQUIT...\n");
break;
}
else
{
printf("**************************\n");
printf("RECV:%s\n",RCV_BUFF);
cmd_result = ftp_cmd_analyse(RCV_BUFF); //解析命令
switch(cmd_result)
{
case CMD_ERROR:
printf("CMD_ERROR!\n");
break;
case CMD_SERVER_LS: //查看服务器文件列表
if(ftp_putlist(connectfd) == -1)
{
printf("List files error!\n");
}
else
{
printf("List files success!\n");
}
break;
case CMD_DOWNLOAD: //客户端从服务器下载文件
printf("Put files:%s\n", RCV_BUFF+9);
if(ftp_putfile(connectfd, RCV_BUFF+9) == -1)
{
printf("Put files error!\n");
}
else
{
printf("Put files success!\n");
}
break;
case CMD_UPLOAD: //客户端上传文件到服务器
printf("Get files:%s\n", RCV_BUFF+7);
if(ftp_getfile(connectfd, RCV_BUFF+7) == -1)
{
printf("Get files error!\n");
}
else
{
printf("Get files success!\n");
}
break;
default:
break;
}
}
}
}
close(connectfd);//客户端退出,断开连接
}
close(sockfd);
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
- linux下基于tcp的FTP编程
- 基于Linux下的TCP编程
- 基于Linux下的TCP编程
- 基于Linux下的TCP编程
- 基于Linux下的TCP编程
- 基于Linux下的TCP编程
- 基于Linux下的TCP编程
- 基于Linux下的TCP编程
- Linux下基于TCP的Socket编程
- 基于Linux下的TCP编程
- Linux下的TCP/IP编程------基于TCP的半关闭
- Linux下的TCP编程
- 基于TCP协议下的socket编程
- 基于Linux的TCP网络编程
- 基于Linux的TCP网络编程
- 基于Linux的TCP网络编程
- 基于Linux的TCP网络编程
- 基于Linux的TCP网络编程
- django model 主键自增问题
- FindContours()函数崩溃问题探索
- Ruby on Rails入门——macOS 下搭建Ruby Rails Web开发环境
- 用shell脚本编写彩色进度条
- 邮件服务器配置(服务器篇):lotus domino 9.0.1安装及配置
- linux下基于tcp的FTP编程
- 负载均衡
- oracle多个字典数据以逗号分隔查询
- 欧姆龙CX-one编程基本知识
- mysql 递归
- RPC框架Thrif数据类型
- 删除数据时检查数据是否被其他数据表使用,其他位置使用了,就不给删除
- Windows下搭建Redis集群
- Python小练习