您的位置:首页 > 理论基础 > 计算机网络

Linux下Socket写http协议下载文件代码以及说明

2008-11-29 10:55 561 查看
项目一部分需要使用socket写http协议,并下载文件,看似简单得问题,调试起来确有一些小小得问题,如果是windows平台的话,自然会简单很多,一个DownloadFile API就可以搞定,可是客户得Proj是在Linux下,不得已,从头开发了。目前得代码由于依然在win下面调试,所以移植得时候稍微注意一下就可以了。

看代码:

#include <string>

#include <iostream>

#include <stdio.h>

#include <winsock.h>

#include <conio.h>

using namespace std;

#pragma comment("ws2_32.lib")

string host2ip(const string& strdomain);

void save2file(char *buffer,const string& filename);

int getlength(const string& sheader);

bool getstatus(const string& sheader);

int getleftlength(const string& sheader);

void sethttphead(const string& file,const string& server);

int port = 80;

int error=0;

string serveraddr;

int i = 0;

const int BUFFER_SIZE = 1024;

char buffer[BUFFER_SIZE] = {0};

char msg[BUFFER_SIZE];

FILE *f;

const string file = "/BT/200801/3/117906.torrent";

const string url = "www.supbt.com";

const string filename = "117906.torrent";

int main(void)

{

int r;

WSADATA wsa;

SOCKET sock;

struct sockaddr_in sin;

f = fopen(filename.c_str(),"ab");

sethttphead(file,url);

if(WSAStartup(MAKEWORD(2,2),&wsa))

{

printf("WSAStartup Error: %d/n",WSAGetLastError());

getche();

return -1;

}

if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)

{

printf("Socket Error: %d/n",WSAGetLastError());

getche();

return -1;

}

sin.sin_family=AF_INET;

sin.sin_port=htons(port);

serveraddr = host2ip(url);

cout << serveraddr << endl;

sin.sin_addr.s_addr=inet_addr(serveraddr.c_str());

if(connect(sock,(struct sockaddr *)&sin,sizeof(sin))==SOCKET_ERROR)

{

printf("Connect Error: %d/n",WSAGetLastError());

printf("请检测网络连接!/n");

getche();

return -1;

}

if((r=send(sock,msg,sizeof(msg),0))==SOCKET_ERROR)

{

printf("Send Error: %d/n",WSAGetLastError());

getche();

return -1;

}

memset(buffer,0,BUFFER_SIZE);

if((r=recv(sock,buffer,BUFFER_SIZE,0))==SOCKET_ERROR)

{

printf("Recv Error: %d/n",WSAGetLastError());

closesocket(sock);

return -1;

}

string header = string(buffer);

int ilength = getlength(header);

int leftlength = ilength;

int icount;

if(getstatus(header)){

//current is r

char *q = buffer;

char *p = strstr(buffer, "/r/n/r/n");

p += 4;

//注意这里得 r - (p-q) 非常关键得问题

fwrite(p,r - (p - q),1,f);

leftlength -= r - (p - q);

int i=0;

icount = r - (p - q);

while(true)

{

memset(buffer, 0, BUFFER_SIZE);

r = recv(sock, buffer, BUFFER_SIZE, 0);

if (r < 0) {

closesocket(sock);

return 2;

}

if (r == 0) {

break;

}

int tmp;

tmp = leftlength; //209 100 100 92

leftlength -= r;

if(leftlength > 0){

fwrite(buffer,r,1,f);

icount += r;

}

else if(leftlength == 0){

//

break;

}

else{

icount += tmp;

fwrite(buffer,tmp,1,f);

break;

}

cout << i++ << " r is "<< r << endl;

}

}else{

cout << "http protocal error" << endl;

}

cout << icount << endl;

fclose(f);

closesocket(sock);

WSACleanup();

getche();

return 0;

}

/*

构造HTTP头

*/

void sethttphead(const string& file,const string& server)

{

strcat(msg,"GET ");

strcat(msg,file.c_str());

strcat(msg," HTTP/1.1");

strcat(msg,"/r/n");

strcat(msg,"Accept:*/*");

strcat(msg,"/r/n");

//strcat(msg,"Accept-Language: zh-cn");

//strcat(msg,"/r/n");

//strcat(msg,"Accept-Encoding: gzip, deflate");

//strcat(msg,"/r/n");

strcat(msg,"User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");

strcat(msg,"/r/n");

strcat(msg,"Host:");

strcat(msg,server.c_str());

strcat(msg,"/r/n");

strcat(msg,"Connection: Keep-Alive");

strcat(msg,"/r/n");

strcat(msg,"/r/n");

}

//---------------------------------------------------------------------------

/*

将domain 转换为IP地址

*/

string host2ip(const string& strdomain)

{

SOCKADDR_IN saddr;

WORD wVersionRequested;

WSADATA wsaData;

hostent *pHostIp;

int nErrorNum;

wVersionRequested = MAKEWORD(2, 2);

nErrorNum = WSAStartup(wVersionRequested, &wsaData);

if(nErrorNum != 0)

{

return "";

}

saddr.sin_family = AF_INET;

pHostIp = gethostbyname(strdomain.c_str());

if(pHostIp == NULL)

{

return "0.0.0.0";

}

WSACleanup();

return (string)inet_ntoa(*(LPIN_ADDR)*(pHostIp->h_addr_list));

}

/*

该方法为测试用法,并为应用到项目中

*/

void save2file(char *buffer,const string& filename)

{

FILE *f;

f = fopen(filename.c_str(),"a+");

fwrite(buffer,strlen(buffer),1,f);

fclose(f);

}

/*

该方法获取待下载文件大小

*/

int getlength(const string& sheader){

char * cont_len_pos;

unsigned long cont_length;

const char* header = sheader.c_str();

cont_len_pos =(char *)strstr(header,"Content-Length:");

cont_len_pos = (char *)strchr(cont_len_pos,' ');

cont_len_pos++;

sscanf(cont_len_pos, "%ld", &cont_length);

return cont_length;

}

/*

该方法判断是否Get成功,不成功就取消下载文件

*/

bool getstatus(const string& sheader){

string start = "HTTP/1.1 200 OK";

if(sheader.find(start,0) != string::npos){

return true;

}

else{

return false;

}

}

/*

该方法并没有用到,开始考虑多了

*/

int getleftlength(const string& sheader){

int nreturnl = 0;

int ilength = sheader.length();

string _send = "/r/n/r/n";

int istart = sheader.find_last_of(_send);

if(istart != string::npos){

nreturnl = ilength - istart -_send.length();

}

return nreturnl;

}

转至http://www.libing.net.cn/post/linux-socket-http-download-file.php
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐