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

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

2012-07-25 16:35 316 查看
项目一部分需要使用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;   
}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐