荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: jjk (UNIX+C+XML+?? 傻了?), 信区: Linux
标  题: linux下面的应用开发起步--小小的网络? guru (转寄)[转载]
发信站: 荔园晨风BBS站 (Thu Apr 25 10:25:50 2002), 转信

【 以下文字转载自 jjk 的信箱 】
【 原文由 jjk.bbs@apue.dhs.org 所发表 】
发信人: guru (好读书,不求甚解), 信区: UNP
标  题: linux下面的应用开发起步--小小的网络蚂蚁(二)(转载)
发信站: UNIX编程 (2001年08月28日18:36:28 星期二), 站内信件


linux下的应用开发起步--简化蚂蚁制作(二)
原创 01-03-17 11:25 185p linuxbird
----------------------------------------------------------------------------
----
3.ok,在初步了解完这些系统调用后,我们就可以开始干活了。
  A.开始定义头文件了。
#ifndef   __ANT_H
#define   __ANT_H
//定义包含库
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <ctype.h>
//定义蚂蚁的最大数目
#define MAXANTNUM  6
//定义缓存大小
#define        BUFSIZE           1500
//从传进来的长字符串分别拣开文件名、域名、路径、端口等
#define        FILENAME          1
#define        SITENAME          2
#define        PATHNAME          3
#define        PORTNAME          4
typedef        char              URL[256];
//定义蚂蚁的数据结构
struct Ant{
int             s;
// URL             mission;
int             position;
int             amount;
char            haversack[BUFSIZE];
int             ready;
};
//定义任务的数据结构
struct Mission{
char    host[100];
u_short port;
URL     url;
};
//是否用代理 0表示不用,1表示用
extern int             use_proxy;
//代理地址
extern char            proxy_server[100];
//代理端口
extern u_short         proxy_port;
//蚂蚁数目
extern int             ant_num;
extern int             bulk;
//下载进度
extern int             progress;
//配置文件
extern char           cfgfile[256];
//日志文件
extern char           logfile[256];
extern struct Ant*    ants[10];
extern struct Mission ms;
//此函数是读取配置文件的
extern      void      read_cfg(char* file);
//此函数是初始化环境的,给变量赋值
extern      void      init_env();
//分配下载任务
extern      int       assign_mission(FILE* log, struct Ant* ant);
//此函数是去掉字符串的空格
extern      void      eat_whitespace(char* str);
//
extern      char*     extract_from_url(URL url,int what);
//从日志文件中取得地址
extern      char*     get_url_from_log(FILE* log);
//返回下载文件的大小
extern      int       get_size_of_url(struct Mission* pms);
//go......下载文件
extern      int       go(struct Ant* ant, struct Mission* pms);
extern      void      enroll(struct Ant* ant, fd_set* rset);
extern      void      unenroll(struct Ant* ant,fd_set* rset);
extern      int       receive(struct Ant* ant, FILE* save);
//如果意外退出,保存当前状态
extern      int       save_status(struct Ant* ant, FILE* log);
#endif
B.在定义完头文件后,下面就可以写辅助函数了,主要是围绕着读取配置、创建连接、
下载文件、保存文件、保存当前蚂蚁状态等。
下面就是funcs.c源码内容
#include "ant.h"
//读取配置文件,并赋予相关变量的值
void
read_cfg(char* cfgfile)
{
FILE* f;
int      i;
char   line[256];
char* p=(char*)NULL;
//判断是否能打开该文件
if((f = fopen(cfgfile, "r")) == (FILE*)NULL){
printf("can not open cfg file ");
exit(1);
}
while(fgets(line, 256, f)!=(char*)NULL){
eat_whitespace(line);//去掉空行(此喂自定义函数)
if(line[0]=='#')
continue;
for(i = 0; line[i]; i++)
line[i]=tolower(line[i]);       //将所有字母转换成小写的
if((p = strstr(line,"use_proxy"))){  //查找代理(proxy)开关设置信息,有则给us
e_proxy=1,否则为0
if(strstr(line,"yes"))
use_proxy=1;
else
use_proxy=0;
}
else if((p = strstr(line,"proxy_server"))){ //查找代理服务器地址设置信息,将
值赋给(proxy_server)
p=strstr(line,"=");
eat_whitespace(++p);
strcpy(proxy_server, p);
}
else if((p = strstr(line, "proxy_port"))){   //查找代理端口设置信息,将值赋给
(proxy_port)
p=strstr(line, "=");
eat_whitespace(++p);
proxy_port=atoi(p);
}
}
}
void
//初始化环境参数,将值赋给各个变量
init_env( )
{
  strcpy(cfgfile, "./ant.conf");
  //取得配置文件名
  read_cfg(cfgfile);
  //取得配置文件中的变量
logfile[0] = cfgfile[0] = 0;
ant_num = MAXANTNUM;
bulk = 0; progress=0;
}
char*
//从记录文件里取得URL地址,断点续传的时候用,函数返回url
get_url_from_log(FILE* log)
{
static  URL   url;
URL           line;
  fseek(log, 0, SEEK_SET);
    //从文件中读取字符串,从起始字符为"#"的行取url
while(fgets(line, sizeof(line)-1, log)!=(char*)NULL){
eat_whitespace(line);
if(line[0]=='#')
continue;
strcpy(url, line);
return url;
}
memset(url,0,sizeof(url));
//内存中为之分配地址
return url;
}
int
//分配下载任务,失败返回0,从上面函数返回的字符中分析出将相关的值赋给数据结构
ant
assign_mission(FILE* log, struct Ant* ant)
{
char        line[256];
char*       p;
while(fgets(line, 256, log)!=(char*)NULL){
eat_whitespace(line);
if((line[0]=='#')||toupper(line[0]=='H')||toupper(line[0]=='F'))
continue;
if(isdigit(line[0])){
ant->position=atoi(line);
p=index(line,':');
ant->amount=atoi(++p);
return 1;
}else
continue;
}
return 0;
}
void
//去掉字符流中的空行
eat_whitespace(char* str)
{
  char* p;
  int i;
  p=str;
  for(i=0; isspace(p[i]); i++ );
  for( ;*p ;p++)
  *p=p[i];
  p=str;
  for(i=strlen(str)-1;isspace(p[i]);i--)
  p[i]=0;
}
char*
//从传进来的url字符串中,分析出文件名、域名、端口名、路径,根据不同的what返回
不同的字串。
extract_from_url(URL  url,int what)
{
static char res[100];
char*       p;
char*       pn;
res[0]=0;
memset(res,0,100);
switch (what){
case FILENAME://分析文件名、若没有用index.html替代(网络默认的首页,呵呵)
p=rindex(url,'/');
if((*(p-1)=='/')||(*(p+1)==0))
strcpy(res,"index.html");
else
strcpy(res,++p);
break;
case PATHNAME:
break;
case SITENAME:      //分析出域名,其中,对ftp,和http做出分类
if((p=index(url, '@')))
   p++;
else{
if((p=strstr(url,"http://")))
p+=7;
else if((p=strstr(url,"ftp://")))
p+=6;
else
p=url;
}
if((pn=index(p,':'))||(pn=index(p,'/'))){
strncpy(res,p,pn-p);
res[pn-p] = 0;
}
else
strcpy(res,p);
break;
case PORTNAME:     //在字符"www.XXXX.com:8080/"之间取得端口号
if((p=rindex(url,':'))&&(*(++p)!='/')){
if((pn=index(p,'/'))){
strncpy(res,p,pn-p);
res[pn-p]=0;
}
else
strcpy(res,p);
}
else{
strcpy(res,"80");
}
break;
}
return res;
}
//
int
//根据传进来的Mission数据结构,建立socket链接,取得文件的大小。
get_size_of_url(struct Mission* pms)
{
int s;
struct sockaddr_in sin;
struct hostent* phe;
char cmd[256];
char msg_hdr[1000];
char* p;
    //准备http中GET 方法的请求。
sprintf(cmd,"GET %s HTTP/1.0 ", pms->url);
   //创建socket
if((s=socket(PF_INET,SOCK_STREAM,0))<0)
return -1;
  //取得远程主机的IP地址,失败函数返回-1
if((phe = gethostbyname(pms->host)) == NULL)
return -1;
memset(&sin,0,sizeof(sin));
memcpy(&sin.sin_addr,phe->h_addr,sizeof(struct in_addr));
sin.sin_family=AF_INET;
sin.sin_port=htons(pms->port);
   //跟远程机器建立连接,失败函数返回-1
if(connect(s,(struct sockaddr*)&sin,sizeof(sin))==-1)
return -1;
   //发送GET请求
if(write(s,cmd,strlen(cmd))<0)
return 0;
//从链接描述符(连接管道)中读取传送过来的数据
if(read(s, msg_hdr, 300)<0)
return 0;
close(s);
printf("%s",msg_hdr);
//读到该文件的大小
if((p=strstr(msg_hdr,"Content-Length"))||(p=strstr(msg_hdr,"Content-length:"
)))
p+=16;
else
return 0;
  //返回大小
return atoi(p);
}
//根据传进来的 ant、mission数据结构,开始下载数据。
int
go(struct Ant* ant, struct Mission* pms)
{
struct sockaddr_in  sin;
struct hostent*     phe;
char                cmd[256];
//准备请求的GET字符
if(ant_num==1)
sprintf(cmd,"GET %s HTTP/1.0 ", pms->url);
sprintf(cmd,"GET %s HTTP/1.0 Range: bytes=%d-%d Cache-Control: no-cache ", p
ms->url,ant->position, ant->position+ant->amount-1);
//为ant数据结构创建套接口
if((ant->s=socket(PF_INET,SOCK_STREAM,0))<0)
return 0;
   //取得远程主机的IP地址,失败返回0
if((phe = gethostbyname(pms->host)) == NULL)
return 0;
memset(&sin,0,sizeof(sin));
memcpy(&sin.sin_addr,phe->h_addr,sizeof(struct in_addr));
sin.sin_family=AF_INET;
sin.sin_port=htons(pms->port);
    //建立连接
if(connect(ant->s,(struct sockaddr*)&sin,sizeof(sin))==-1)
return 0;
   //发送读取请求
if(write(ant->s,cmd,strlen(cmd))<0)
return 0;
printf("Connect Host:%s , port:%d ",pms->host,pms->port);
printf("%s",cmd);
return 1;
}
void
enroll(struct Ant* ant, fd_set* rset)
{
FD_SET(ant->s,rset);
}
void
unenroll(struct Ant* ant, fd_set* rset)
{
FD_CLR(ant->s,rset);
}
int
//把传进来的数据结构ant的数据存储起来
receive(struct Ant* ant, FILE* save)
{
int     as;
int     length;
char* p;
if((length = read(ant->s, ant->haversack, BUFSIZE)) >= 0){
p=ant->haversack;
if(!ant->ready){
ant->ready=1;
p=strstr(ant->haversack, " ");
p+=4;
length-=(p-ant->haversack);
}
}
else{
return 0;
}
if(0 == fseek(save, ant->position, SEEK_SET)){
if(0 <= fwrite(p, sizeof(char), length, save)){
ant->amount-=length;
ant->position+=length;
return length;
}
}
return 0;
}
int
//保存当前的蚂蚁数目,以及状态
save_status(struct Ant* ant, FILE* log)
{
return fprintf(log,"%d:%d ",ant->position,ant->amount);
}

--
一头栽倒luckylucky的怀里
※ 来源:·UNIX编程 www.tiaozhan.com/unixbbs/·[FROM: 202.114.1.61] --
※ 转载:·UNIX编程 www.tiaozhan.com/unixbbs/·[FROM: 202.114.36.225]
--
※ 转寄:·UNIX编程 apue.dhs.org·[FROM: 210.39.3.50]
--
※ 转载:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.146]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店