⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.cpp

📁 Visual C++网络通信编程实用案例精选光盘内容6-9章
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//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 + -