用HTTP协议下载一个MP3文件

来源:互联网 发布:java并发编程实战 epub 编辑:程序博客网 时间:2024/04/29 13:19

在visual studio上调试通过的,这个只是一个示例,还有很多不完善的细节(鲁棒性)需要考虑。

主要流程:

1)创建一个TCP连接
2)发送一个HTTP GET命令
3)读取一段数据,解析出Content-Length字段,找到MP3文件的长度
4)循环读取数据,直到读取到的数据量大于等于MP3文件的长度

#include "stdafx.h"#include <Winsock2.h>#include <iostream>  #include <cstdio> #pragma comment(lib, "ws2_32.lib")int _tmain(int argc, _TCHAR* argv[]){    const char CTL_STR[] = "Content-Length";// 加载socket动态链接库(dll)      WORD wVersionRequested;      WSADATA wsaData;    // 这结构是用于接收Wjndows Socket的结构信息的      int err;      FILE *hFile = fopen("out.mp3","wb");    wVersionRequested = MAKEWORD( 1, 1 );   // 请求1.1版本的WinSock库      err = WSAStartup( wVersionRequested, &wsaData );      if ( err != 0 ) {          return -1;          // 返回值为零的时候是表示成功申请WSAStartup      }      if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {          // 检查这个低字节是不是1,高字节是不是1以确定是否我们所请求的1.1版本          // 否则的话,调用WSACleanup()清除信息,结束函数          WSACleanup( );          return -1;       }  // 创建socket操作,建立流式套接字,返回套接字号sockClient      // SOCKET socket(int af, int type, int protocol);      // 第一个参数,指定地址簇(TCP/IP只能是AF_INET,也可写成PF_INET)      // 第二个,选择套接字的类型(流式套接字),第三个,特定地址家族相关协议(0为自动)      SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);  // 将套接字sockClient与远程主机相连      // int connect( SOCKET s,  const struct sockaddr* name,  int namelen);      // 第一个参数:需要进行连接操作的套接字      // 第二个参数:设定所需要连接的地址信息      // 第三个参数:地址的长度      SOCKADDR_IN addrSrv;      addrSrv.sin_addr.S_un.S_addr = inet_addr("61.155.41.53");     ;       addrSrv.sin_family = AF_INET;      addrSrv.sin_port = htons(80);      connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));      char cmd_str[] = "GET /speeches/obama/Obama%202017-01-13%20Weekly%20Address%20-%20The%20Honor%20of%20Serving%20You%20as%20President.mp3 HTTP/1.1\r\nHOST:www.listeningexpress.com\r\n\r\n";    //通过 TCP 连接,发送 HTTP GET命令    send(sockClient, cmd_str, strlen(cmd_str), 0);      char recvBuf[3001];     int iResult = 0 ;    int i;    int j;    iResult = recv(sockClient, recvBuf, 3000, 0);      char len_str[100];    //to find the "Content-Length"     for(i=0;i<iResult;i++)    {        for( j =0; j<strlen(CTL_STR); j++)            if(recvBuf[i+j] != CTL_STR[j])                break;        if(j == strlen(CTL_STR) )        {            i += j;            break;        }    }    //to get the "Content-Length"    j=0;    for(;i<iResult;i++)    {        if( recvBuf[i] >= '0' && recvBuf[i] <= '9')        {            len_str[j] = recvBuf[i];            len_str[j+1] = 0;            j++;        }        if( (recvBuf[i] == 0x0d) && (recvBuf[i+1] == 0x0a))            break;    }    int length_ctr = atoi(len_str);    //to find the END of Header    for(i=0;i<iResult;i++)    {        if( (recvBuf[i] == 0x0d) && (recvBuf[i+1] == 0x0a) && (recvBuf[i+2] == 0x0d) && (recvBuf[i+3] == 0x0a) )            break;    }    int current_len = iResult - i - 4 ;    fwrite(&recvBuf[i+4], 1, current_len, hFile);    i=1;    do{          memset(recvBuf,0,3001);        iResult = recv(sockClient, recvBuf, 3000, 0);          if(iResult > 0)        {            fwrite(recvBuf, 1, iResult, hFile);            current_len+= iResult;        }        else            printf("no data \n");        if( current_len >= length_ctr )            break;        i++;    }while(iResult > 0);      printf("End linking...\n");      closesocket(sockClient);      WSACleanup();   // 终止对套接字库的使用      fclose(hFile);    printf("\n");      system("pause");      return 0;}
0 0
原创粉丝点击