📄 ftp.c
字号:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <netdb.h> //gethostbyname
#include <stdlib.h> //malloc
#include <stdarg.h> //va_list
//数据段的结构
struct bindex{
unsigned long start;
unsigned long end;
};
pthread_t g_tid[10]; //工作线程的tid,最多10个
struct bindex g_tsk[10]; //工作线程的任务起点和终点
//工作线程传入结构
struct antsdata{
char* serverip;
char* user;
char* pass;
char* enfile;
int port;
unsigned long *spos;
unsigned long *epos;
};
//统一的消息输出
void logmsg(char* fmt,...)
{
va_list args;
va_start(args,fmt);
vprintf(fmt, args);
va_end(args);
}
//ftp://user:pass@111.111.111.111:21/file/files.c
//返回1正确,返回0错误
int islegalurl(char *url)
{
char h[7];
memcpy(h,url,6);
h[6]=0;
return strcmp("ftp://",h)==0?1:0;
}
//域名解析函数,把例如www.xxx.com翻译成ip地址
//如果输入的是IP地址,返回同样的地址。
//返回1成功,返回0失败
//server 服务器名
//sip 存放ip地址的空间
//buflen sip空间长度
//本函数用到头文件为netdb.h
int getserverip(char *server,char *sip,int buflen)
{
struct hostent *host;
if((host=gethostbyname(server))==NULL) {
logmsg("==>获取ip地址失败,可能是查询DNS的问题。\n");
return 0;
} else {
if(NULL != inet_ntop(AF_INET,(void*)(host->h_addr),sip,buflen)) {
logmsg("==>获取ip地址成功。\n");
return 1;
}else{
logmsg("==>获取ip地址失败,可能是地址缓冲不够的问题。\n");
return 0;
}
}
}
//通过url提取用户名和口令信息
//返回1成功,0失败
int getuserandpassbyurl(char *url,char *user,int ulen,char *pass,int plen)
{
//寻找@,如果有则服务器从@后开始,到/结束
//如果没有,则从ftp://开始
char *p=url;
while(*p!='@' && *p!=0) p++;
if(*p=='@'){
char *e=p-1;
char *p=e;
while(*p!='/' && p>url) p--;
if(p==url) {
logmsg("找到@,但没找到前面的/,错误。\n");
return 0; //没找到前面的斜杠
}else {
char *s=p+1;
assert(e>s);
int len=e-s+1;
//search ':'
while(*p!=':' && p<e) p++;
if(p==e) {
logmsg("没找到分割用户和密码的冒号,错误。\n");
return 0; //无冒号分割
}
if(ulen < p-s+1) {
logmsg("用户名的空间不够,错误。\n");
return 0;
}
memcpy(user,s,p-s);
user[p-s]=0;
if(plen < e-p+1) {
logmsg("口令空间不够,错误。\n");
return 0;
}
memcpy(pass,p+1,e-p);
pass[e-p]=0;
return 1;
}
}else{
if(ulen < 11 || plen < 8 ) {
logmsg("用户名或口令空间不够,错误。\n");
return 0;
}
strcpy(user,"anonymous");
strcpy(pass,"miniftp");
return 1;
}
}
int getserverandportbyurl(char *url,char *server,int *port,int buflen /*server长度*/)
{
//寻找@,如果有则服务器从@后开始,到/结束
//如果没有,则从ftp://开始
char *p=url;
while(*p!='@' && *p!=0) p++;
if(*p=='@')
{
char *s=p+1;
while(*p!='/' && *p!=0) p++;
if(*p=='/')
{
int len=p-s; //包含端口在内的长度
//检查是否包含了端口在内
char *ck=p-1;
while(*ck!=':' && ck >s ) ck--;
if(ck==s) {//无端口
if(buflen < len+1) return 0;
memcpy(server,s,len);
server[len]=0;
*port=21;
return 1;
}else {
//有端口
int slen=ck-s;
int plen=len-slen-1;
if(buflen < slen) return 0;
memcpy(server,s,slen);
server[slen]=0;
char prt[8];
memcpy(prt,ck+1,plen);
prt[plen]=0;
*port=atoi(prt);
return 1;
}
}
else
{
return 0;
}
}
else //到了结尾没有@
{
p=url;
while(*p!='/' && *p!=0) p++;
p++;
while(*p!='/' && *p!=0) p++;
p++;
char *s=p;
while(*p!='/' && *p!=0) p++;
printf("3\n");
if(*p=='/') {
int len=p-s; //包含端口在内的长度
//检查是否包含了端口在内
char *ck=p-1;
while(*ck!=':' && ck >s ) ck--;
if(ck==s) {//无端口
if(buflen < len+1) return 0;
memcpy(server,s,len);
server[len]=0;
*port=21;
return 1;
}else {
//有端口
int slen=ck-s;
int plen=len-slen-1;
if(buflen < slen) return 0;
memcpy(server,s,slen);
server[slen]=0;
char prt[8];
memcpy(prt,ck+1,plen);
prt[plen]=0;
*port=atoi(prt);
return 1;
}
}else{
return 0;
}
}
}
//从url中获得文件段的数据
//不检查是否为目录,也不进行编码
int getfilebyurl(char* url,char *fn,int buflen)
{
//ftp://dfasdfas.com/dfad/dfs
//找第三个'/'
char *p=url;
while(*p!='/' && *p!=0) p++;
if(*p==0) {
logmsg("url格式不对\n");
return 0;
}
p++;
while(*p!='/' && *p!=0) p++;
if(*p==0) {
logmsg("url格式不对\n");
return 0;
}
p++;
while(*p!='/' && *p!=0) p++;
if(*p==0) {
logmsg("url格式不对\n");
return 0;
}
if(buflen< strlen(url)-(p-url)) {
logmsg("文件名空间不够。\n");
return 0;
}
memcpy(fn,p,strlen(url)-(p-url));
fn[strlen(url)-(p-url)]=0;
return 1;
}
//建立物理连接,成功返回socket,失败<0
int makeconn(char *server,int port)
{
struct sockaddr_in servaddr;
int sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0) {
logmsg("建立socket失败\n");
return -1;
}
memset(&servaddr,0,sizeof(struct sockaddr_in));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(port);
//inet_aton(server,&servaddr.sin_addr)<=0);
if(inet_pton(AF_INET,server,&servaddr.sin_addr)<=0)
{
logmsg("不正确的ip地址\n");
return -2;/*Ip Error*/
}
if(connect(sock,(struct sockaddr*)&servaddr,sizeof(struct sockaddr_in))<0)
{
logmsg("连接失败,可能是网络不可达。\n");
return -3;/*connect error*/
}
return sock;
}
/*
建立ftp控制连接,成功返回socket,失败<0
*/
int makectrlconn(char *server,int port)
{
int sock;
if((sock=makeconn(server,port))<0) {
return sock;
}else{
if(220==getretcode(sock))
{
return sock; //connect ok
}
else
{
logmsg("服务器回应了应用失败\n");
close(sock);
return -4;
}
}
}
/*
FTP登录
fail if <0
*/
int login(int sock,char *user,char *pass)
{
int nret;
char buffer[256];
sprintf(buffer,"USER %s\r\n",user);
if(sendout(sock,buffer,strlen(buffer))<0) {
logmsg("网络发送失败\n");
return -1; //write data error
}
nret=getretcode(sock);
if(nret>=500) {
logmsg("拒绝用户登录\n");
return -2;
}
if(nret==230) return 0;
sprintf(buffer,"PASS %s\r\n",pass);
if(sendout(sock,buffer,strlen(buffer))<0) {
logmsg("网络发送失败\n");
return -1; //write data error
}
nret=getretcode(sock);
if(nret!=230) {
logmsg("用户或密码无效,登录失败\n");
return -3;
}
return 0;
}
//获得返回的命令码
int getretcode(int sock)
{
int nret;
char buffer[1024];
int movepos=0;
while(linefeedpos(buffer,movepos)==-1) //没有结束一行
{
if(movepos>1000) return -3; //buffer runs out
if((nret=read(sock,buffer+movepos,1024-movepos))<=0) {
logmsg("网络失败");
return -2; //read data error
}
movepos+=nret;
}
if(movepos<5) {
logmsg("服务器返回的数据无效\n");
return -2;
}
//读返回码
char code[4];
memcpy(code,buffer,3);
code[4]=0;
return atoi(code);
}
//发出数据
int sendout(int sock,char *buf,int len)
{
int pos=0;
int nRet=0;
while(pos<len)
{
nRet=write(sock,buf+pos,len-pos);
if(nRet==0)
{
logmsg("对方关闭连接,发送失败。\n");
return -2;
}
else if(nRet==-1)
{
logmsg("网络故障发送失败\n");
return -1;
}
else
{
pos+=nRet;
if(pos!=len)
{
continue;
}
else
{
return pos;
}
}
}
}
//if no linefeed return -1
//数据中是否有回车换行?
int linefeedpos(char *buffer,int movepos)
{
int i;
for(i=0;i<=movepos-2;i++)
if(buffer[i]=='\r' && buffer[i+1]=='\n')
return i;
return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -