分享
 
 
 

一个简单的http下载程序

王朝other·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

最近研究了一下http协议,用C++在linux下写了一个简单的http下载程序,程序的功能很简单,在终端输入文件所在网址,程序会单线程从服务器上下载该文件到本地。程序里面涉及了socket编程、http协议、二进制文件的写入。有兴趣的兄弟可以随便看看,玩具而已,大家一起玩玩了。

对于Http协议不是很了解的兄弟,可以去http://biz.chinabyte.com/209/2151709.shtml 看看,对于初学者,这篇文章是相当不错的。

所有源码可以到http://www.kunxu.com/kun/download/code/C/http_client.rar 下载

下面贴出来的是文件的源码:

CSocket.h:

#ifndef __CSOCKET_H__

#define __CSOCKET_H__

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <stdarg.h>

#include <string.h>

#include <errno.h>

#include <netdb.h>

#include <fcntl.h>

#include <sys/time.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <string>

#include <iostream>

using namespace std;

typedef enum socket_type { SERVER_TYPE = 0, CLIENT_TYPE } s_type;

typedef enum socket_state{ CONN_ERROR = -1, CONN_OK = 0, CONN_WAIT = 1 } s_state;

class Sock_instance

{

public:

Sock_instance(string hostname, unsigned port, s_type type);

~Sock_instance();

bool Connect();

int fd();

s_state state();

bool Send(string msg);

int Receive();

void Close();

unsigned char* data() const;

int datalen() const;

string http_head() const;

private:

string _hostname;

unsigned _port;

int _fd;

s_state _state;

s_type _type;

unsigned char *_data;

int _datalen;

string _http_head;

};

#endif

CSocket.cpp:

#include "CSocket.h"

Sock_instance::Sock_instance(string hostname, unsigned port, s_type type)

: _hostname( hostname ),

_port( port ),

_fd( 0 ),

_state( CONN_ERROR ),

_type( type )

{

_datalen = 0;

_data = new unsigned char[1024*1024];

}

Sock_instance::~Sock_instance()

{

delete[] _data;

}

bool Sock_instance::Connect()

{

if( _type == SERVER_TYPE )

{

cout << "The socket is a server, don't use conncet!" << endl;

return false;

}

struct sockaddr_in peer;

int fd;

bzero( &peer, sizeof(peer) );

peer.sin_family = AF_INET;

struct hostent *hp = gethostbyname( _hostname.c_str() );

if ( hp == NULL )

{

cout << "unknow host: " << _hostname << endl;

return false;

}

peer.sin_addr = *( ( struct in_addr * )hp->h_addr );

peer.sin_port = htons(_port);

cout << "conncet to " << inet_ntoa(peer.sin_addr) << ": " << ntohs( peer.sin_port ) << endl;

fd = socket( AF_INET, SOCK_STREAM, 0 );

if ( fd < 0 )

{

cout << "socket call failed" << endl;

return false;

}

if( connect( fd, (struct sockaddr *)&peer, sizeof( peer ) ) )

{

cout << errno << "connect failed" << endl;

_state = CONN_ERROR;

close( fd );

return false;

}

_state = CONN_OK;

_fd = fd;

return true;

}

s_state Sock_instance::state()

{

return _state;

}

int Sock_instance::fd()

{

return _fd;

}

bool Sock_instance::Send(string msg)

{

if( state() != CONN_OK )

{

cout << "the socket is not ok" << endl;

return false;

}

int rc;

if((rc = send(_fd, msg.c_str(), msg.size(), 0)) == -1)

{

if((errno != EWOULDBLOCK) && (errno != EAGAIN))

{

_state = CONN_ERROR;

return false;

}

}

return true;

}

int Sock_instance::Receive()

{

int rc;

char buf[BUFSIZ];

char *p_buf = buf;

static bool b_readhead = true;

bzero(buf, BUFSIZ);

if((rc = recv( _fd, buf, BUFSIZ - 1, 0 )) < 0 )

{

cout << "recive error" << endl;

_state = CONN_WAIT;

Close();

}

else if( rc == 0 )

{

cout << "server teminated" << endl;

_state = CONN_WAIT;

Close();

}

else

{

//read HTTP head

int ix = 0;

while( b_readhead )

{

// 2 0D 0A just for head end

if( ix >= rc )

break;

if( buf[ix] == 13 && buf[ix+1] == 10 && buf[ix+2] == 13 && buf[ix+3] == 10 )

{

b_readhead = false;

char *p = new char[ix+5];

memset( p, 0, ix+5 );

memcpy( p, buf, ix+5 );

p_buf += ix + 5;

_http_head = p;

delete[] p;

cout << _http_head << endl;

break;

}

ix ++;

}

//copy data to _data

if( ix != 0 && ix < rc )

{

//this buf has head so data begin with buf+ix+4

memcpy( _data+_datalen, buf+ix+4, rc-ix-4 );

_datalen += rc-ix-4;

}

else

{

memcpy( _data+_datalen, buf, rc );

_datalen += rc;

}

}

return rc;

}

inline void Sock_instance::Close()

{

close( _fd );

}

//string Sock_instance::data() const

unsigned char * Sock_instance::data() const

{

return _data;

}

int Sock_instance::datalen() const

{

return _datalen;

}

string Sock_instance::http_head() const

{

return _http_head;

}

http_main.cpp:

#include "CSocket.h"

#include <fstream>

int main()

{

string word;

string filename;

string hostname;

int pos1 = 0;

int pos2 = 0;

cout << "enter the host name" << endl;

cin >> word;

//bulid the query for http

string quest = "GET ";

quest += word;

quest += " HTTP/1.0\r\n";

quest += "User-agent:Mozilla/4.0\r\n";

quest += "Accept-language:zh-cn\r\n\r\n";

//get the hostname and filename from the word

string str_http = "http://";

pos1 = word.find_first_of (str_http, 0);

pos2 = word.find_first_of ("/", pos1+7);

hostname = word.substr( pos1+7, pos2-pos1-7 );

pos1 = word.find_last_of( "/", word.size() );

filename = word.substr( pos1+1, word.size()-pos1-1 );

cout << "filename: " << filename << endl;

cout << "hostname: " << hostname << endl;

//use the hostname and port 80 to connect

Sock_instance s_client( hostname, 80, CLIENT_TYPE );

if( !s_client.Connect() )

{

cout << "connect error" << endl;

return -1;

}

//send the http query to the host

cout << "connect is ok!" << endl;

if( !s_client.Send(quest) )

{

cout << "send is error!" << endl;

return -1;

}

//recieve all the file from the hsot

while( s_client.Receive() > 0 )

{

}

//write the binary data which is recieved on the file

FILE *fp = fopen( filename.c_str(), "wb" );

fwrite( s_client.data(), sizeof( unsigned char ), s_client.datalen(), fp );

fclose( fp );

return 0;

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有