⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 306.htm

📁 unix高级编程原吗
💻 HTM
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>apue</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center">               ● UNIX网络编程                       (BM: clown)                </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p   align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="301.htm">上一层</a>][<a href="307.htm">下一篇</a>]
<hr><p align="left"><small>发信人: guru (好读书,不求甚解), 信区: UNP <br>

标  题: linux下面的应用开发起步--小小的网络蚂蚁(二)(转载) <br>

发信站: UNIX编程 (2001年08月28日18:36:28 星期二), 站内信件 <br>

  <br>

【 以下文字转载自 APUE 讨论区 】 <br>

【 原文由 chillone 所发表 】 <br>

  <br>

linux下的应用开发起步--简化蚂蚁制作(二) <br>

原创 01-03-17 11:25 185p linuxbird <br>

---------------------------------------------------------------------------- <br>

---- <br>

3.ok,在初步了解完这些系统调用后,我们就可以开始干活了。 <br>

  A.开始定义头文件了。 <br>

#ifndef   __ANT_H <br>

#define   __ANT_H <br>

//定义包含库 <br>

#include <stdio.h> <br>

#include <stdlib.h> <br>

#include <string.h> <br>

#include <sys/types.h> <br>

#include <sys/socket.h> <br>

#include <netinet/in.h> <br>

#include <netdb.h> <br>



#include <unistd.h> <br>

#include <ctype.h> <br>

//定义蚂蚁的最大数目 <br>

#define MAXANTNUM  6 <br>

//定义缓存大小 <br>

#define        BUFSIZE           1500 <br>

//从传进来的长字符串分别拣开文件名、域名、路径、端口等 <br>

#define        FILENAME          1 <br>

#define        SITENAME          2 <br>

#define        PATHNAME          3 <br>

#define        PORTNAME          4 <br>

typedef        char              URL[256]; <br>

//定义蚂蚁的数据结构 <br>

struct Ant{ <br>

int             s; <br>

// URL             mission; <br>

int             position; <br>

int             amount; <br>

char            haversack[BUFSIZE]; <br>

int             ready; <br>

}; <br>

//定义任务的数据结构 <br>



struct Mission{ <br>

char    host[100]; <br>

u_short port; <br>

URL     url; <br>

}; <br>

//是否用代理 0表示不用,1表示用 <br>

extern int             use_proxy; <br>

//代理地址 <br>

extern char            proxy_server[100]; <br>

//代理端口 <br>

extern u_short         proxy_port; <br>

//蚂蚁数目 <br>

extern int             ant_num; <br>

extern int             bulk; <br>

//下载进度 <br>

extern int             progress; <br>

//配置文件 <br>

extern char           cfgfile[256]; <br>

//日志文件 <br>

extern char           logfile[256]; <br>

extern struct Ant*    ants[10]; <br>

extern struct Mission ms; <br>



//此函数是读取配置文件的 <br>

extern      void      read_cfg(char* file); <br>

//此函数是初始化环境的,给变量赋值 <br>

extern      void      init_env(); <br>

//分配下载任务 <br>

extern      int       assign_mission(FILE* log, struct Ant* ant); <br>

//此函数是去掉字符串的空格 <br>

extern      void      eat_whitespace(char* str); <br>

// <br>

extern      char*     extract_from_url(URL url,int what); <br>

//从日志文件中取得地址 <br>

extern      char*     get_url_from_log(FILE* log); <br>

//返回下载文件的大小 <br>

extern      int       get_size_of_url(struct Mission* pms); <br>

//go......下载文件 <br>

extern      int       go(struct Ant* ant, struct Mission* pms); <br>

extern      void      enroll(struct Ant* ant, fd_set* rset); <br>

extern      void      unenroll(struct Ant* ant,fd_set* rset); <br>

extern      int       receive(struct Ant* ant, FILE* save); <br>

//如果意外退出,保存当前状态 <br>

extern      int       save_status(struct Ant* ant, FILE* log); <br>

#endif <br>

#endif <br>

B.在定义完头文件后,下面就可以写辅助函数了,主要是围绕着读取配置、创建连接、 <br>

下载文件、保存文件、保存当前蚂蚁状态等。 <br>

下面就是funcs.c源码内容 <br>

#include "ant.h" <br>

//读取配置文件,并赋予相关变量的值 <br>

void <br>

read_cfg(char* cfgfile) <br>

{ <br>

FILE* f; <br>

int      i; <br>

char   line[256]; <br>

char* p=(char*)NULL; <br>

//判断是否能打开该文件 <br>

if((f = fopen(cfgfile, "r")) == (FILE*)NULL){ <br>

printf("can not open cfg file "); <br>

exit(1); <br>

} <br>

while(fgets(line, 256, f)!=(char*)NULL){ <br>

eat_whitespace(line);//去掉空行(此喂自定义函数) <br>

if(line[0]=='#') <br>

continue; <br>

for(i = 0; line[i]; i++) <br>



line[i]=tolower(line[i]);       //将所有字母转换成小写的 <br>

if((p = strstr(line,"use_proxy"))){  //查找代理(proxy)开关设置信息,有则给us <br>

e_proxy=1,否则为0 <br>

if(strstr(line,"yes")) <br>

use_proxy=1; <br>

else <br>

use_proxy=0; <br>

} <br>

else if((p = strstr(line,"proxy_server"))){ //查找代理服务器地址设置信息,将 <br>

值赋给(proxy_server) <br>

p=strstr(line,"="); <br>

eat_whitespace(++p); <br>

strcpy(proxy_server, p); <br>

} <br>

else if((p = strstr(line, "proxy_port"))){   //查找代理端口设置信息,将值赋给 <br>

(proxy_port) <br>

p=strstr(line, "="); <br>

eat_whitespace(++p); <br>

proxy_port=atoi(p); <br>

} <br>

} <br>

} <br>

} <br>

void <br>

//初始化环境参数,将值赋给各个变量 <br>

init_env( ) <br>

{ <br>

  strcpy(cfgfile, "./ant.conf"); <br>

  //取得配置文件名 <br>

  read_cfg(cfgfile); <br>

  //取得配置文件中的变量 <br>

logfile[0] = cfgfile[0] = 0; <br>

ant_num = MAXANTNUM; <br>

bulk = 0; progress=0; <br>

} <br>

char* <br>

//从记录文件里取得URL地址,断点续传的时候用,函数返回url <br>

get_url_from_log(FILE* log) <br>

{ <br>

static  URL   url; <br>

URL           line; <br>

  fseek(log, 0, SEEK_SET); <br>

    //从文件中读取字符串,从起始字符为"#"的行取url <br>

while(fgets(line, sizeof(line)-1, log)!=(char*)NULL){ <br>

eat_whitespace(line); <br>



if(line[0]=='#') <br>

continue; <br>

strcpy(url, line); <br>

return url; <br>

} <br>

memset(url,0,sizeof(url)); <br>

//内存中为之分配地址 <br>

return url; <br>

} <br>

int <br>

//分配下载任务,失败返回0,从上面函数返回的字符中分析出将相关的值赋给数据结构 <br>

ant <br>

assign_mission(FILE* log, struct Ant* ant) <br>

{ <br>

char        line[256]; <br>

char*       p; <br>

while(fgets(line, 256, log)!=(char*)NULL){ <br>

eat_whitespace(line); <br>

if((line[0]=='#')||toupper(line[0]=='H')||toupper(line[0]=='F')) <br>

continue; <br>

if(isdigit(line[0])){ <br>

ant->position=atoi(line); <br>



p=index(line,':'); <br>

ant->amount=atoi(++p); <br>

return 1; <br>

}else <br>

continue; <br>

} <br>

return 0; <br>

} <br>

void <br>

//去掉字符流中的空行 <br>

eat_whitespace(char* str) <br>

{ <br>

  char* p; <br>

  int i; <br>

  p=str; <br>

  for(i=0; isspace(p[i]); i++ ); <br>

  for( ;*p ;p++) <br>

  *p=p[i]; <br>

  p=str; <br>

  for(i=strlen(str)-1;isspace(p[i]);i--) <br>

  p[i]=0; <br>

} <br>

} <br>

char* <br>

//从传进来的url字符串中,分析出文件名、域名、端口名、路径,根据不同的what返回 <br>

不同的字串。 <br>

extract_from_url(URL  url,int what) <br>

{ <br>

static char res[100]; <br>

char*       p; <br>

char*       pn; <br>

res[0]=0; <br>

memset(res,0,100); <br>

switch (what){ <br>

case FILENAME://分析文件名、若没有用index.html替代(网络默认的首页,呵呵) <br>

p=rindex(url,'/'); <br>

if((*(p-1)=='/')||(*(p+1)==0)) <br>

strcpy(res,"index.html"); <br>

else <br>

strcpy(res,++p); <br>

break; <br>

case PATHNAME: <br>

break; <br>

case SITENAME:      //分析出域名,其中,对ftp,和http做出分类 <br>

if((p=index(url, '@'))) <br>



   p++; <br>

else{ <br>

if((p=strstr(url,"http://"))) <br>

p+=7; <br>

else if((p=strstr(url,"ftp://"))) <br>

p+=6; <br>

else <br>

p=url; <br>

} <br>

if((pn=index(p,':'))||(pn=index(p,'/'))){ <br>

strncpy(res,p,pn-p); <br>

res[pn-p] = 0; <br>

} <br>

else <br>

strcpy(res,p); <br>

break; <br>

case PORTNAME:     //在字符"www.XXXX.com:8080/"之间取得端口号 <br>

if((p=rindex(url,':'))&&(*(++p)!='/')){ <br>

if((pn=index(p,'/'))){ <br>

strncpy(res,p,pn-p); <br>

res[pn-p]=0; <br>

} <br>

} <br>

else <br>

strcpy(res,p); <br>

} <br>

else{ <br>

strcpy(res,"80"); <br>

} <br>

break; <br>

} <br>

return res; <br>

} <br>

// <br>

int <br>

//根据传进来的Mission数据结构,建立socket链接,取得文件的大小。 <br>

get_size_of_url(struct Mission* pms) <br>

{ <br>

int s; <br>

struct sockaddr_in sin; <br>

struct hostent* phe; <br>

char cmd[256]; <br>

char msg_hdr[1000]; <br>

char* p; <br>

    //准备http中GET 方法的请求。 <br>



sprintf(cmd,"GET %s HTTP/1.0 ", pms->url); <br>

   //创建socket <br>

if((s=socket(PF_INET,SOCK_STREAM,0))<0) <br>

return -1; <br>

  //取得远程主机的IP地址,失败函数返回-1 <br>

if((phe = gethostbyname(pms->host)) == NULL) <br>

return -1; <br>

memset(&sin,0,sizeof(sin)); <br>

memcpy(&sin.sin_addr,phe->h_addr,sizeof(struct in_addr)); <br>

sin.sin_family=AF_INET; <br>

sin.sin_port=htons(pms->port); <br>

   //跟远程机器建立连接,失败函数返回-1 <br>

if(connect(s,(struct sockaddr*)&sin,sizeof(sin))==-1) <br>

return -1; <br>

   //发送GET请求 <br>

if(write(s,cmd,strlen(cmd))<0) <br>

return 0; <br>

//从链接描述符(连接管道)中读取传送过来的数据 <br>

if(read(s, msg_hdr, 300)<0) <br>

return 0; <br>

close(s); <br>

printf("%s",msg_hdr); <br>



//读到该文件的大小 <br>

if((p=strstr(msg_hdr,"Content-Length"))||(p=strstr(msg_hdr,"Content-length:" <br>

))) <br>

p+=16; <br>

else <br>

return 0; <br>

  //返回大小 <br>

return atoi(p); <br>

} <br>

//根据传进来的 ant、mission数据结构,开始下载数据。 <br>

int <br>

go(struct Ant* ant, struct Mission* pms) <br>

{ <br>

struct sockaddr_in  sin; <br>

struct hostent*     phe; <br>

char                cmd[256]; <br>

//准备请求的GET字符 <br>

if(ant_num==1) <br>

sprintf(cmd,"GET %s HTTP/1.0 ", pms->url); <br>

sprintf(cmd,"GET %s HTTP/1.0 Range: bytes=%d-%d Cache-Control: no-cache ", p <br>

ms->url,ant->position, ant->position+ant->amount-1); <br>

//为ant数据结构创建套接口 <br>



if((ant->s=socket(PF_INET,SOCK_STREAM,0))<0) <br>

return 0; <br>

   //取得远程主机的IP地址,失败返回0 <br>

if((phe = gethostbyname(pms->host)) == NULL) <br>

return 0; <br>

memset(&sin,0,sizeof(sin)); <br>

memcpy(&sin.sin_addr,phe->h_addr,sizeof(struct in_addr)); <br>

sin.sin_family=AF_INET; <br>

sin.sin_port=htons(pms->port); <br>

    //建立连接 <br>

if(connect(ant->s,(struct sockaddr*)&sin,sizeof(sin))==-1) <br>

return 0; <br>

   //发送读取请求 <br>

if(write(ant->s,cmd,strlen(cmd))<0) <br>

return 0; <br>

printf("Connect Host:%s , port:%d ",pms->host,pms->port); <br>

printf("%s",cmd); <br>

return 1; <br>

} <br>

void <br>

enroll(struct Ant* ant, fd_set* rset) <br>

{ <br>

{ <br>

FD_SET(ant->s,rset); <br>

} <br>

void <br>

unenroll(struct Ant* ant, fd_set* rset) <br>

{ <br>

FD_CLR(ant->s,rset); <br>

} <br>

int <br>

//把传进来的数据结构ant的数据存储起来 <br>

receive(struct Ant* ant, FILE* save) <br>

{ <br>

int     as; <br>

int     length; <br>

char* p; <br>

if((length = read(ant->s, ant->haversack, BUFSIZE)) >= 0){ <br>

p=ant->haversack; <br>

if(!ant->ready){ <br>

ant->ready=1; <br>

p=strstr(ant->haversack, " "); <br>

p+=4; <br>

length-=(p-ant->haversack); <br>

} <br>

} <br>

} <br>

else{ <br>

return 0; <br>

} <br>

if(0 == fseek(save, ant->position, SEEK_SET)){ <br>

if(0 <= fwrite(p, sizeof(char), length, save)){ <br>

ant->amount-=length; <br>

ant->position+=length; <br>

return length; <br>

} <br>

} <br>

return 0; <br>

} <br>

int <br>

//保存当前的蚂蚁数目,以及状态 <br>

save_status(struct Ant* ant, FILE* log) <br>

{ <br>

return fprintf(log,"%d:%d ",ant->position,ant->amount); <br>

} <br>

  <br>

-- <br>

一头栽倒luckylucky的怀里 <br>



※ 来源:·UNIX编程 www.tiaozhan.com/unixbbs/·[FROM: 202.114.1.61] -- <br>

※ 转载:·UNIX编程 www.tiaozhan.com/unixbbs/·[FROM: 202.114.36.225] <br>

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="301.htm">上一层</a>][<a href="307.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -