經過http協議下載MP3的關鍵就是 整塊打包,一塊一塊向文件裏面存儲。讀取的時候用二進制服務器
/***
szWebAddr: 頁面地址(包含host+addr)app
szMp3FileName:將要存儲文件的名字
szRequest: 請求內容
szHeadEx: http頭附加信息(替換其默認的設置)
iReqType: 請求類型(1--Get;2--Post)
iTimeout: 超時時間(秒)
返回: 頁面返回數據
**/socket
int GetDataFromWebByte(char *szWebAddr,char *szMp3FileName , char *szRequest, char *szHeadEx, int iReqType, int iTimeout) { char szHost[128] = "", szAddr[512] = ""; char szWebBuf[4096] = "", szBuf[4096] = ""; char *pRetData = NULL; //返回的數據 char *szHead = NULL; int iPort = 80, iAppSock; int iRet = 0, iLen, k, iChars, iDone; int iContentLen, iChunked = 0; struct sockaddr_in appHostAddr; struct hostent *pHostent = NULL; int iTransferType = 0, iContent = 0; FILE *fp; WSADATA wsa={0}; if(!szWebAddr) return 0; WSAStartup(MAKEWORD(2,2),&wsa); //獲取host和addr和port iRet = GetHostandAddr(szWebAddr, szHost, sizeof(szHost), szAddr, sizeof(szAddr), &iPort); if(iRet < 1) return 0; //獲取hostent pHostent = gethostbyname(szHost); if(!pHostent) { iRet = WSAGetLastError(); return 0; } //建立socket appHostAddr.sin_family = AF_INET; appHostAddr.sin_port = htons((unsigned short)iPort); appHostAddr.sin_addr.s_addr = ((struct in_addr *)(pHostent->h_addr))->s_addr; iAppSock = socket(AF_INET, SOCK_STREAM, 0); if(iAppSock == -1) { return 0; } //將建立的Socket鏈接至應用服務器 if(connect(iAppSock, (void *)&appHostAddr, sizeof(appHostAddr)) == -1) { return 0; } //配置httphead szHead = GetHttpHead(szHost, szAddr, szRequest, szHeadEx, iReqType); if(!szHead) return 0; //嚮應用服務器發送HTTP請求 if(send(iAppSock, szHead, strlen(szHead), 0) == -1){ return 0; } free(szHead); szHead = NULL; //接收應用服務器返回的數據 memset(szWebBuf, 0, sizeof(szWebBuf)); memset(szBuf, 0, sizeof(szBuf)); k = 0; iChars = 0; iDone = 0; //獲取http頭信息 while(iDone == 0) { iLen = RecvHttpData(iAppSock, szWebBuf, 1, iTimeout); if(iLen < 1) iDone = 1; switch(*szWebBuf) { case '\r': break; case '\n': if(iChars == 0) iDone = 1; iChars = 0; break; default: iChars++; break; } if(k < sizeof(szBuf) - 1) { szBuf[k] = szWebBuf[0]; k++; } else { pRetData = addRevData(pRetData, szBuf); memset(szBuf, 0, sizeof(szBuf)); k = 0; szBuf[k] = szWebBuf[0]; k++; } } pRetData = addRevData(pRetData, szBuf); //獲取http內容長度 //判斷是否chunked if(strstr(pRetData, "chunked")) iChunked = 1; //爲chunk傳輸 //獲取http內容 iContent = 1; do { if (iChunked > 0) { iContentLen = GetChunkedContentLength(iAppSock); } else { iContentLen = GetContentLength(pRetData); } //獲取http內容 //清空數據 if(iContent == 1 && pRetData) { free(pRetData); pRetData = NULL; iContent = 2; } if(iContentLen < 1) { closesocket(iAppSock); //close(iAppSock); return 1; } //chunk memset(szWebBuf, 0, sizeof(szWebBuf)); memset(szBuf, 0, sizeof(szBuf)); k = 0; iChars = iContentLen; //*iLenByte = iChars; iDone = 0; fp = fopen(szMp3FileName , "wb+"); while(iDone == 0) { iLen = RecvHttpData(iAppSock, szWebBuf, 1, iTimeout); if(iLen < 1) iDone = 1; iChars--; if(iChars < 1) iDone = 1; if(k < sizeof(szBuf) - 1) { szBuf[k] = szWebBuf[0]; k++; } else { // puts(szBuf); fwrite(szBuf,1,4096,fp); memset(szBuf, 0, sizeof(szBuf)); k = 0; szBuf[k] = szWebBuf[0]; k++; } } fclose(fp); } while (iChunked); //chunk格式才繼續找 closesocket(iAppSock); WSACleanup(); return 1; }
塊的大小結合實際狀況,卻大越好,過小的時候,噪音的頻率會很高,影響質量,具體消除噪音,之後再改進。spa