📄 client.cpp
字号:
//Http multithread download tools
//by caucy 2006.2.18
#include "stdafx.h"
#include "Client.h"
#include <winsock2.h>
#include <afxsock.h>
#include <assert.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
#include <sys/TIMEB.H>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
using namespace std;
#define BUFFER_BLOCK_SIZE 4096
#define DEAL_SOCK_ERROR(retCode,sock) if((retCode)==SOCKET_ERROR || (retCode)==0)\
{ \
cout<<"Sock error: "<<GetLastError()<<endl;\
closesocket(sock); \
return -1; \
}
#define NUM_OF_MAX_THREADS 5
#define HUGE_DATA_SIZE (1024*BUFFER_BLOCK_SIZE)
struct HTTP_Request_Struct
{
string proxyServerName;
UINT proxyServerPort;
string proxyUser;
string proxyPass;
string serverHostName;
UINT serverPort;
string url;
};
struct HTTP_Thread_Struct
{
HTTP_Request_Struct request;
int rangerStart;
int dutyLength;
};
//Auxiliary Functions
void Date(string& date);
int HttpRequest();
u_long ConvertHostnameToLongHostAddress(const char * destAddress);
void RenameFileName(string& filename);
void GivenUniqueFileName(const string& dir,
const string& subject,
string& name,
string postfix);
void SplitURLToHostAndSubURL(const string& url, string& hostname, string& suburl);
void SplitURLToNameAndPostfix(const string& src, string& name, string& postfix);
void SplitURLToHostAndFilename(const string& url, string& hostname, string& filename);
//Agent Application Functions
int Get(const HTTP_Request_Struct& request, string& filename);
void GetStartString(string& str, string& startStr);
BOOL FilterStartTag(string& str, const string& tag);
BOOL FilterSourceImageURL(string& body, string& url);
void EncodingBase64(const char* src, char* des);
int Socks5StartIPv4(const HTTP_Request_Struct& request, SOCKET& sock);
int HttpProxyStart(const HTTP_Request_Struct& request, SOCKET& sock);
DWORD WINAPI DownloadThread(LPVOID p);
int ConnectToServer(const HTTP_Request_Struct& request, SOCKET& sock);
ofstream g_File;
HANDLE g_WriteEvent;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
HttpRequest();
return 0;
}
int HttpRequest()
{
string filename;
HTTP_Request_Struct request;
request.serverPort=80;
// request.url="http://10.10.10.80/noclass/InitialD/NI.LabWindows.CVI.v8.0/NI.LabWindows.CVI.v8.0.iso";
SplitURLToHostAndFilename(request.url, request.serverHostName, filename);
if(request.url.find("http:/",0)==string::npos)
{
request.url=string("http://")+request.url;
}
if(filename=="/")
{
if(request.url.find_last_of('/',request.url.length())!=request.url.length()-1)
request.url+="/";
}
// request.proxyServerName=""; //Proxy Server IP
// request.proxyServerPort=808; //Http Proxy
// request.proxyServerPort=1080; //SOCKS Proxy
// request.proxyUser="";
// request.proxyPass="";
WSADATA wsaData;
if(WSAStartup(MAKEWORD( 2, 2 ), &wsaData)!=0)
cerr<<"socket init error"<<endl;
if(Get(request, filename)==-1)
cout<<"Unsuccessfully request."<<endl;
return 0;
}
DWORD WINAPI DownloadThread(LPVOID p)
{
HTTP_Thread_Struct *pRequest=(HTTP_Thread_Struct*)p;
int retCode;
SOCKET sock;
string str;
string::size_type pos;
char buffer[BUFFER_BLOCK_SIZE+1];
char filter[BUFFER_BLOCK_SIZE+1];
const int WRITE_BLOCK_SIZE=100*BUFFER_BLOCK_SIZE;
char *pWriteBuffer;
string head;
int contentLength;
int filepos;
BOOL bProcessHead=TRUE;
int tag;
if(ConnectToServer(pRequest->request,sock)==-1)
return -1;
pWriteBuffer= new char[WRITE_BLOCK_SIZE+1];
//1. GET Command
contentLength=0;
filepos=pRequest->rangerStart;
sprintf(buffer,"GET %s HTTP/1.1\r\nHost: %s\r\nRange: bytes=%d-%d\r\n\r\n",pRequest->request.url.c_str(),pRequest->request.serverHostName.c_str(),pRequest->rangerStart,pRequest->rangerStart+pRequest->dutyLength-1);
cout<<buffer;
cout.flush();
send(sock,buffer,strlen(buffer),0);
while(1)
{
retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
if(retCode==0 || retCode==-1)
goto _exit;
if(bProcessHead)
{
buffer[retCode]='\0';
cout<<buffer;
cout.flush();
head+=buffer;
if((pos=head.find("\r\n\r\n",0))!=string::npos)
{
pos=head.find("\r\n",0);
strcpy(filter,head.substr(0,pos).c_str());
if(sscanf(string(filter).c_str(),"%s%d",filter,&tag)==-1 || tag/100!=2)
goto _exit;
pos=head.find("\r\n\r\n",0);
contentLength=pos+4-contentLength;
//strncpy(pWriteBuffer,buffer+contentLength,retCode-contentLength);
memcpy(pWriteBuffer,buffer+contentLength,(retCode-contentLength)*sizeof(char));
contentLength=retCode-contentLength;
bProcessHead=FALSE;
}
else
contentLength+=retCode;
}
else
{
//strncpy(pWriteBuffer+contentLength,buffer,retCode);
memcpy(pWriteBuffer+contentLength,buffer,retCode);
contentLength+=retCode;
if(contentLength>=WRITE_BLOCK_SIZE-BUFFER_BLOCK_SIZE || pRequest->dutyLength-contentLength<=0)
{
WaitForSingleObject(g_WriteEvent, INFINITE);
g_File.seekp(filepos);
pRequest->dutyLength-=contentLength;
if(pRequest->dutyLength<=0)
{
assert(pRequest->dutyLength==0);
g_File.write(pWriteBuffer,pRequest->dutyLength+contentLength);
filepos+=contentLength;
SetEvent(g_WriteEvent);
goto _exit;
}
else
{
cout<<".";
cout.flush();
g_File.write(pWriteBuffer,contentLength);
filepos+=contentLength;
SetEvent(g_WriteEvent);
}
contentLength=0;
}
}
}
_exit:
closesocket(sock);
delete[] pWriteBuffer;
return 0;
}
int Get(const HTTP_Request_Struct& request, string& filename)
{
int retCode;
SOCKET sock;
string::size_type pos;
char buffer[BUFFER_BLOCK_SIZE+1];
char filter[BUFFER_BLOCK_SIZE+1];
string head;
int contentLength,fileLength;
int tag;
ofstream file;
BOOL bProcessHead=TRUE;
char *p;
if(ConnectToServer(request,sock)==-1)
return -1;
GivenUniqueFileName("",string(filename),filename,"");
g_File.open(filename.c_str(),ios::binary);
assert(!g_File.fail());
//1. GET Command
sprintf(buffer,"GET %s HTTP/1.1\r\nHost: %s\r\n\r\n",request.url.c_str(),request.serverHostName.c_str());
cout<<buffer;
cout.flush();
send(sock,buffer,strlen(buffer),0);
contentLength=0;
while(1)
{
retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
if(retCode==-1)
{
closesocket(sock);
return -1;
}
if(retCode==0)
{
cout<<endl<<"File finished!"<<endl;
g_File.close();
closesocket(sock);
return 0;
}
if(bProcessHead)
{
buffer[retCode]='\0';
cout<<buffer;
cout.flush();
strcpy(filter,buffer);
_strlwr(filter);
head+=filter;
if((pos=head.find("\r\n\r\n",0))!=string::npos)
{
pos=head.find("\r\n",0);
strcpy(filter,head.substr(0,pos).c_str());
if(sscanf(string(filter).c_str(),"%s%d",filter,&tag)==-1 || tag/100!=2)
{
closesocket(sock);
return -1;
}
strcpy(filter,"\r\ncontent-length:");
if((p=strstr(head.c_str(),filter))!=NULL)
{
p+=strlen(filter);
strcpy(filter,p);
if(sscanf(filter,"%d",&fileLength)==-1)
{
closesocket(sock);
return -1;
}
cout<<"File length: "<<fileLength<<endl;
cout.flush();
if(fileLength>2*HUGE_DATA_SIZE)
{
cout<<"Multithread downloading is taken...."<<endl;
cout.flush();
goto _MT_DOWNLOAD;
}
else
{
cout<<"Single Thread downloading is taken...."<<endl;
cout.flush();
pos=head.find("\r\n\r\n",0);
contentLength=pos+4-contentLength;
g_File.write(buffer+contentLength,retCode-contentLength);
fileLength-=(retCode-contentLength);
}
}
else
{
cout<<"Single Thread downloading is taken...."<<endl;
cout.flush();
pos=head.find("\r\n\r\n",0);
contentLength=pos+4-contentLength;
g_File.write(buffer+contentLength,retCode-contentLength);
fileLength-=(retCode-contentLength);
}
bProcessHead=FALSE;
}
else
contentLength+=retCode;
}
else
{
cout<<".";
cout.flush();
g_File.write(buffer,retCode);
fileLength-=retCode;
if(fileLength==0)
{
closesocket(sock);
return 0;
}
}
}
//the first body content is save in buffer and the length is content length
//3. Filter request return code
_MT_DOWNLOAD:
closesocket(sock);
int dutyLength=HUGE_DATA_SIZE;
int threadNum= fileLength/HUGE_DATA_SIZE;
if(threadNum>NUM_OF_MAX_THREADS)
{
threadNum=NUM_OF_MAX_THREADS;
dutyLength=fileLength/threadNum;
}
g_WriteEvent = CreateEvent(NULL,FALSE,TRUE,NULL);
HANDLE *pThreadHand= new HANDLE[threadNum];
HTTP_Thread_Struct *pHttpThreadPara = new HTTP_Thread_Struct[threadNum];
for(int i=0; i<threadNum-1; i++)
{
pHttpThreadPara[i].request=request;
pHttpThreadPara[i].dutyLength=dutyLength;
pHttpThreadPara[i].rangerStart=dutyLength*i;
pThreadHand[i]=CreateThread(NULL,0,DownloadThread,pHttpThreadPara+i,0,NULL);
}
pHttpThreadPara[i].request=request;
pHttpThreadPara[i].rangerStart=dutyLength*i;
pHttpThreadPara[i].dutyLength=fileLength-pHttpThreadPara[i].rangerStart;
pThreadHand[i]=CreateThread(NULL,0,DownloadThread,pHttpThreadPara+i,0,NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -