[转帖]HTTP实现断点再续

从HTTP服务器上下载一个文件有很多方法,“热心”的微软提供了 WinInet 类,用起来也很方便。当然,我们也可以自己实现这些功能,通过格式化请求头很容易就能实现断点续传和检查更新等等功能 。 
1. 连接主机 
2. 格式化请求头 
3. 设置接收,发送超时 
  
要想从服务器下载文件,首先要向服务器发送一个请求。HTTP 请求头由若干行字符串组成。下面结合实例说说 HTTP 请求头的格式。假设要下载 http://www.sina.com.cn/index.html 这个网页 ,那么请求头的写法如下:

第1行:方法,请求的内容,HTTP协议的版本
下载一般可以用GET方法,请求的内容是“/index.html”,HTTP协议的版本是指浏览器支持的版本,对于下载软件来说无所谓,所以用1.1版 “HTTP/1.1”;
“GET /index.html HTTP/1.1”

第2行:主机名,格式为“Host:主机”
在这个例子中是:“Host:www.sina.com.cn”

第3行:接受的数据类型,下载软件当然要接收所有的数据类型,所以:
“Accept:*/*”

第4行:指定浏览器的类型
有些服务器会根据客户服务器种类的不同会增加或减少一些内容,在这个例子中可以这样写:
“User-Agent:Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)”
第5行:连接设置
设定为一直保持连接:“Connection:Keep-Alive”

第6行:若要实现断点续传则要指定从什么位置起接收数据,格式如下:
“Range: bytes=起始位置 - 终止位置”
比如要读前500个字节可以这样写:“Range: bytes=0 - 499”;从第 1000 个字节起开始下载:
“Range: bytes=999 -”
最后,别忘了加上一行空行,表示请求头结束。整个请求头如下:
GET /index.html HTTP/1.1
Host:www.sina.com.cn
Accept:*/*
User-Agent:Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)
Connection:Keep-Alive
下面用例子看看如何进行断点的下载吧

// DownloadFile.h: interface for the CDownloadFile class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_DOWNLOADFILE_H__E9A59779_BEF9_4A78_8D0E_ED8C9498E07C__INCLUDED_)
#define AFX_DOWNLOADFILE_H__E9A59779_BEF9_4A78_8D0E_ED8C9498E07C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define NOTIFY_MSG_WPARAM_GENDOWNFILEID 0x01

#define NOTIFY_MSG_LOW_WPARAM_FULLSIZE 0x10
#define NOTIFY_MSG_LOW_WPARAM_CURRENTSIZE 0x20
#define NOTIFY_MSG_LOW_WPARAM_DOWNSIZE 0x30
#define NOTIFY_MSG_LOW_WPARAM_DOWNSPEED 0x40

class CDownloadFile 
{
public:
BOOL OpenRedirectHttpURL(CString &strOldLocation,CInternetSession &cSession);
BOOL DownLoadFile(LPCTSTR lpFileURL,LPCTSTR lpSaveFile);
CDownloadFile();
virtual ~CDownloadFile();
LPCTSTR GetSavedFileName() { return m_strSaveToFile;}
LPCTSTR GetDownURL() { return m_strFileURL;}

public:
WORD GenFileID();
void RegisterNotifyWindow(DWORD dwThreadID,HWND hWnd,DWORD dwMsg);
BOOL GetUNCFile();
bool m_bForceReload;
DWORD m_TimeOut;
WORD m_wFileID;

protected:
DWORD m_dwThreadID;
void PostNotifyMessage(WPARAM wParam, LPARAM lParam);
DWORD m_dwMsgID;
HWND m_hNotify;
BOOL GetFtpFile(CInternetSession &cSession);
BOOL GetHttpFile(CInternetSession &cSession);
CString m_strTmpFileName;
CString m_strFileURL;
CString m_strSaveToFile;
CString m_rawHeaders;
float m_transferRate;
DWORD m_infoStatusCode;
};

#endif // !defined(AFX_DOWNLOADFILE_H__E9A59779_BEF9_4A78_8D0E_ED8C9498E07C__INCLUDED_)

// DownloadFile.cpp: implementation of the CDownloadFile class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DownloadFile.h"

#pragma comment( lib,"Wininet.lib" )

#include "shlwapi.h"
#pragma comment( lib,"shlwapi.lib" )

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define BUFFER_SIZE 4095

const TCHAR szHeaders[] = _T("Accept: */*\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)\r\n");

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDownloadFile::CDownloadFile()
{
m_TimeOut = 0;
m_bForceReload = true;
m_dwThreadID = 0;
m_hNotify = NULL;
m_dwMsgID = 0;
m_wFileID = 0;
}

CDownloadFile::~CDownloadFile()
{

}

BOOL CDownloadFile::DownLoadFile(LPCTSTR lpFileURL, LPCTSTR lpSaveFile)
{
BOOL bRet = FALSE;
if ( !::PathIsURL(lpFileURL) )
{
return bRet;
}
m_strSaveToFile = lpSaveFile;
m_strFileURL = lpFileURL;
m_strTmpFileName = lpSaveFile;
m_strTmpFileName += _T(".df!");
CString strServer,strObject;INTERNET_PORT nPort;
CString strAgentCaption = _T("Update Download ") ;
strAgentCaption += ::PathFindFileName(lpSaveFile);
DWORD dwFlags = 0;
InternetGetConnectedState(&dwFlags, 0);
CInternetSession session (strAgentCaption, 1,

(dwFlags & INTERNET_CONNECTION_PROXY) == INTERNET_CONNECTION_PROXY ? INTERNET_OPEN_TYPE_PRECONFIG : INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY,
NULL, NULL, 0);
AfxParseURL(m_strFileURL,dwFlags,strServer,strObject,nPort);

if (m_TimeOut != 0)
session.SetOption(INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, m_TimeOut);
if( !m_wFileID )
m_wFileID = GenFileID();
PostNotifyMessage(NOTIFY_MSG_WPARAM_GENDOWNFILEID,m_wFileID);

try
{
if ( dwFlags== AFX_INET_SERVICE_HTTP )
{
bRet = GetHttpFile(session);
}
else if( dwFlags== AFX_INET_SERVICE_FTP )
{
bRet = GetFtpFile(session);
}
else if( dwFlags== AFX_INET_SERVICE_FILE )
{
if( UrlIsFileUrl(m_strFileURL) )
bRet = GetUNCFile();
}
else
{
;

}
catch (CException* pEx)
{
TCHAR szErrorMsg[MAX_PATH] = {0};
pEx->GetErrorMessage(szErrorMsg, MAX_PATH);
TRACE( _T("Exception: %s\n") , szErrorMsg);
pEx->Delete();
}

session.Close();
m_wFileID = 0;
if (bRet)
{
if (!::MoveFileEx(m_strTmpFileName,m_strSaveToFile,MOVEFILE_REPLACE_EXISTING) )
{
Sleep(1000);
::MoveFileEx(m_strTmpFileName,m_strSaveToFile,MOVEFILE_REPLACE_EXISTING);
}
}
return bRet;
}

BOOL CDownloadFile::GetHttpFile(CInternetSession &cSession)
{
BOOL bRet = FALSE;
CFile m_TmpFile;
CFileException fileException;

if ( !m_TmpFile.Open (m_strTmpFileName, 
CFile::modeCreate | CFile::modeNoTruncate | CFile::modeReadWrite
| CFile::shareDenyWrite | CFile::typeBinary,
&fileException ) )
{
TRACE( _T("Open File failed: %d\n"), fileException.m_cause );
return bRet;
}
CString strRangeQuest;

if (m_TmpFile.GetLength()>0)
{
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_CURRENTSIZE,m_wFileID),m_TmpFile.GetLength());
m_TmpFile.SeekToEnd();
strRangeQuest.Format( _T("%sRange: bytes=%d-\r\n"), szHeaders,m_TmpFile.GetLength());
}
else
strRangeQuest = szHeaders;

DWORD dwCount = 0;
CHttpFile* pFile = NULL;
CString strTmpURL = m_strFileURL;
try
{
DWORD dwFlags = INTERNET_FLAG_TRANSFER_BINARY 
|INTERNET_FLAG_DONT_CACHE
|INTERNET_FLAG_PRAGMA_NOCACHE
;
if (m_bForceReload) {
dwFlags |= INTERNET_FLAG_RELOAD;
}
//Here Find URLFile Redirect.
// OpenRedirectHttpURL(strTmpURL,cSession);
pFile = (CHttpFile*) cSession.OpenURL(strTmpURL, 1, dwFlags,strRangeQuest, -1);
}
catch (CInternetException* e)
{
TCHAR szCause[MAX_PATH] = {0};
e->GetErrorMessage(szCause, MAX_PATH);
e->Delete();
delete pFile;
pFile = NULL;
return bRet;
}

COleDateTime startTime = COleDateTime::GetCurrentTime();
DWORD dwHttpFileSize = 0;
if (pFile)
{
BYTE buffer[BUFFER_SIZE+1] = {0};
try {
UINT nRead = 0;
pFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,dwHttpFileSize);
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_FULLSIZE,m_wFileID),dwHttpFileSize);
TRACE( _T("Totoal Length is %d\n"), dwHttpFileSize );
dwCount = 0;
do
{
nRead = pFile->Read(buffer, BUFFER_SIZE);
if (nRead > 0)
{
buffer[nRead] = 0;
m_TmpFile.Write(buffer,nRead);

COleDateTimeSpan elapsed = COleDateTime::GetCurrentTime() - startTime;
double dSecs = elapsed.GetTotalSeconds();
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_DOWNSIZE,m_wFileID),dwCount);
if (dSecs > 0.0)
{
dwCount += nRead;
m_transferRate = (float) ( dwCount / 1024.0 / dSecs );
TRACE("Read %d bytes (%0.1f Kb/s)\n", dwCount, m_transferRate );
}
else
{
TRACE("Read %d bytes\n", dwCount);
m_transferRate = (float) ( dwCount / 1024.0 );
}
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_DOWNSPEED,m_wFileID),(LPARAM)m_transferRate);
}
}
while (nRead > 0);
bRet = TRUE;
}
catch (CFileException *e)
{
TCHAR szCause[MAX_PATH] = {0};
e->GetErrorMessage(szCause, MAX_PATH);
TRACE("ErrorMsg : %s\n", szCause);
e->Delete();
delete pFile;
m_TmpFile.Close();
return FALSE;
}
pFile->QueryInfoStatusCode(m_infoStatusCode); 
pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS ,m_rawHeaders);
pFile->Close();
m_TmpFile.Close();
delete pFile;
}

return bRet;
}

BOOL CDownloadFile::OpenRedirectHttpURL(CString &strOldLocation,CInternetSession &cSession)
{
BOOL bRet = FALSE;
CHttpFile *pFile = NULL;
CHttpConnection* pServer = NULL;
CString strServerName,strObject;
INTERNET_PORT nPort = 0;
DWORD dwServiceType = 0;

if (!AfxParseURL(strOldLocation, dwServiceType, strServerName, strObject, nPort) ||
dwServiceType != INTERNET_SERVICE_HTTP)
{
TRACE( _T("Not A Http Quest!\n") );
return bRet;
}

pServer = cSession.GetHttpConnection(strServerName, nPort);

pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,
strObject, NULL, 1, NULL, NULL, 
INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_AUTO_REDIRECT);
pFile->AddRequestHeaders(szHeaders);
pFile->SendRequest();

DWORD dwRet;
pFile->QueryInfoStatusCode(dwRet);

// if access was denied, prompt the user for the password

if (dwRet == HTTP_STATUS_DENIED)
{
DWORD dwPrompt;
dwPrompt = pFile->ErrorDlg(NULL, ERROR_INTERNET_INCORRECT_PASSWORD,
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL);

// if the user cancelled the dialog, bail out

if (dwPrompt != ERROR_INTERNET_FORCE_RETRY)
{
TRACE( _T("Access denied: Invalid password\n") );
// close up the redirected site

pFile->Close();
delete pFile;
pServer->Close();
delete pServer;

return bRet;
}

pFile->SendRequest();
pFile->QueryInfoStatusCode(dwRet);
}

// were we redirected?
// these response status codes come from WININET.H

if (dwRet == HTTP_STATUS_MOVED ||
dwRet == HTTP_STATUS_REDIRECT ||
dwRet == HTTP_STATUS_REDIRECT_METHOD)
{
CString strNewLocation;
pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation);
int nPlace = strNewLocation.Find(_T("Location: "));
if (nPlace == -1)
{
TRACE( _T("Error: Site redirects with no new location\n") );
// close up the redirected site

pFile->Close();
delete pFile;
pServer->Close();
delete pServer;
return bRet;

strNewLocation = strNewLocation.Mid(nPlace + 10);
nPlace = strNewLocation.Find('\n');
if (nPlace > 0)
strNewLocation = strNewLocation.Left(nPlace);
strOldLocation = strNewLocation;
}
if ( dwRet == HTTP_STATUS_OK )
{
bRet = TRUE;
}
// close up the redirected site
pFile->Close();
delete pFile;
pServer->Close();
delete pServer;

return bRet;
}

BOOL CDownloadFile::GetFtpFile(CInternetSession &cSession)
{
BOOL bRet = FALSE;
CFile m_TmpFile;
CFileException fileException;

if ( !m_TmpFile.Open (m_strTmpFileName, 
CFile::modeCreate | CFile::modeNoTruncate | CFile::modeReadWrite
| CFile::shareDenyWrite | CFile::typeBinary,
&fileException ) )
{
TRACE( _T("Open File failed: %d\n"), fileException.m_cause );
return bRet;
}

DWORD dwCount = 0;
CFtpConnection *pFtpConn = NULL;
CInternetFile *pFile = NULL;
try
{
CString strServerName,strObject,strUserName,strPassword;
INTERNET_PORT nPort = 0;
DWORD dwServiceType = 0;
CString strRestPointCommand;

if (!AfxParseURLEx(m_strFileURL, dwServiceType, strServerName, strObject, nPort, 
strUserName, strPassword) ||
dwServiceType != INTERNET_SERVICE_FTP)
{
TRACE( _T("Not A Ftp Quest!\n") );
}
// CFtpConnection ERROR_INTERNET_NO_DIRECT_ACCESS CInternetSession
if (strUserName.IsEmpty())
pFtpConn = cSession.GetFtpConnection(strServerName,NULL,NULL,nPort,m_bForceReload);
else
pFtpConn = cSession.GetFtpConnection(strServerName,strUserName,strPassword,nPort,m_bForceReload);
if (m_TmpFile.GetLength())
{
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_CURRENTSIZE,m_wFileID),m_TmpFile.GetLength());
m_TmpFile.SeekToEnd();
strRestPointCommand.Format( _T("REST %d"), m_TmpFile.GetLength());
//strRestPointCommand.Format( _T("ls") );
if ( !FtpCommand((*pFtpConn), FALSE, FTP_TRANSFER_TYPE_ASCII, 
strRestPointCommand, 0, 0) )
{
TRACE( _T("FtpCommand failed, error: %d\n"), GetLastError());
m_TmpFile.SeekToBegin();

}
if (pFtpConn)
{
pFile = pFtpConn->OpenFile(strObject);
}
}
catch (CInternetException* e)
{
TCHAR szCause[MAX_PATH] = {0};
e->GetErrorMessage(szCause, MAX_PATH);
e->Delete();
delete pFile;
delete pFtpConn;
return bRet;
}

COleDateTime startTime = COleDateTime::GetCurrentTime();
DWORD dwFtpFileSize = 0;
if (pFile)
{
BYTE buffer[BUFFER_SIZE+1] = {0};
try {
UINT nRead = 0;
dwFtpFileSize = FtpGetFileSize( (*pFile),0);
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_FULLSIZE,m_wFileID),dwFtpFileSize);
TRACE( _T("Totoal Length is %d\n"), dwFtpFileSize );
dwCount = 0;
do
{
nRead = pFile->Read(buffer, BUFFER_SIZE);
if (nRead > 0)
{
buffer[nRead] = 0;
m_TmpFile.Write(buffer,nRead);

COleDateTimeSpan elapsed = COleDateTime::GetCurrentTime() - startTime;
double dSecs = elapsed.GetTotalSeconds();
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_DOWNSIZE,m_wFileID),dwCount);
if (dSecs > 0.0)
{
dwCount += nRead;
m_transferRate = (float)(dwCount / 1024.0 / dSecs);
TRACE("Read %d bytes (%0.1f Kb/s)\n", dwCount, m_transferRate ); 
}
else
{
TRACE("Read %d bytes\n", dwCount);
m_transferRate = (float)(dwCount / 1024.0);
}
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_DOWNSPEED,m_wFileID),(LPARAM)m_transferRate);
}
}
while (nRead > 0);
bRet = TRUE;
}
catch (CFileException *e)
{
TCHAR szCause[MAX_PATH] = {0};
e->GetErrorMessage(szCause, MAX_PATH);
TRACE("ErrorMsg : %s\n", szCause);
e->Delete();
delete pFile;
pFtpConn->Close();
delete pFtpConn;
m_TmpFile.Close();
return FALSE;
}
pFile->Close();
delete pFile;
m_TmpFile.Close();
pFtpConn->Close();
delete pFtpConn;
}
return bRet;
}

BOOL CDownloadFile::GetUNCFile()
{
BOOL bRet = FALSE;
CFile m_TmpFile,m_SrcFile;
CFileException fileException;
CString strOldLocation = m_strFileURL;
if ( !m_TmpFile.Open (m_strTmpFileName, 
CFile::modeCreate | CFile::modeNoTruncate | CFile::modeReadWrite
| CFile::shareDenyWrite | CFile::typeBinary,
&fileException ) )
{
TRACE( _T("Open File failed: %d\n"), fileException.m_cause );
return bRet;
}
strOldLocation.TrimLeft();
strOldLocation.TrimRight();
if( StrCmpNI(strOldLocation, _T("file:/"),6) == 0 )
{
strOldLocation = strOldLocation.Mid(8);
strOldLocation.Replace( _T('/'), _T('\\'));
}

if ( !m_SrcFile.Open ( strOldLocation, 
CFile::modeRead | CFile::shareDenyWrite | CFile::typeBinary,
&fileException ) )
{
TRACE( _T("Open File failed: %d\n"), fileException.m_cause );
return bRet;
}
COleDateTime startTime = COleDateTime::GetCurrentTime();
DWORD dwCount = 0;
try {
if (m_TmpFile.GetLength())
{
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_CURRENTSIZE,m_wFileID),m_TmpFile.GetLength());
m_TmpFile.SeekToEnd();
m_SrcFile.Seek(m_TmpFile.GetLength(), CFile::begin);
}
BYTE buffer[BUFFER_SIZE+1] = {0};
UINT nRead = 0;
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_FULLSIZE,m_wFileID),m_SrcFile.GetLength());
TRACE( _T("Totoal Length is %d,left is %d\n"), m_SrcFile.GetLength() ,m_SrcFile.GetLength() - m_TmpFile.GetLength());
dwCount = 0;
do
{
nRead = m_SrcFile.Read(buffer, BUFFER_SIZE);
if (nRead > 0)
{
buffer[nRead] = 0;
m_TmpFile.Write(buffer,nRead);

COleDateTimeSpan elapsed = COleDateTime::GetCurrentTime() - startTime;
double dSecs = elapsed.GetTotalSeconds();
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_DOWNSIZE,m_wFileID),dwCount);
if (dSecs > 0.0)
{
dwCount += nRead;
m_transferRate = (float)(dwCount / 1024.0 / dSecs);
TRACE("Read %d bytes (%0.1f Kb/s)\n", dwCount, m_transferRate ); 
}
else
{
TRACE("Read %d bytes\n", dwCount);
m_transferRate = (float)(dwCount / 1024.0);
}
PostNotifyMessage(MAKEWPARAM(NOTIFY_MSG_LOW_WPARAM_DOWNSPEED,m_wFileID),(LPARAM)m_transferRate);
}
}
while (nRead > 0);
bRet = TRUE;
}
catch (CFileException *e)
{
TCHAR szCause[MAX_PATH] = {0};
e->GetErrorMessage(szCause, MAX_PATH);
TRACE("ErrorMsg : %s\n", szCause);
e->Delete();
m_TmpFile.Close();
return FALSE;
}
m_TmpFile.Close();
return bRet;
}

void CDownloadFile::RegisterNotifyWindow(DWORD dwThreadID,HWND hWnd, DWORD dwMsg)
{
m_dwThreadID = dwThreadID;
m_hNotify = hWnd;
m_dwMsgID = dwMsg;
}

void CDownloadFile::PostNotifyMessage(WPARAM wParam, LPARAM lParam)
{
if (m_hNotify)
{
::PostMessage(m_hNotify, m_dwMsgID, wParam, lParam);
}
if ( m_dwThreadID )
{
::PostThreadMessage(m_dwThreadID,m_dwMsgID, wParam, lParam);
}
}

WORD CDownloadFile::GenFileID()
{
srand(GetTickCount());
return rand() & 0xFFFF;
}
UINT ThreadDownSingleFile( LPVOID pParam )
{
CDownloadFile m_DownFile;
UINT uRet = 0;
if (lpDownParam)
{
m_DownFile.m_wFileID = m_DownFile.GenFileID();
//这里注册通知窗口和消息
//m_DownFile.RegisterNotifyWindow
if ( m_DownFile.DownLoadFile(m_Msg.lpFileSrc, m_Msg.lpFileDst) )
{
uRet = 1;
}
}
return uRet;
}

时间: 2024-10-15 10:43:29

[转帖]HTTP实现断点再续的相关文章

IBM——TSM数据存储与备份的管理

TSM(Tivoli Storage Manager) 软件是IBM 存储管理经验的结晶.TSM 是为解决企业级数据及系统安全而设计的备份全面解决方案,为石油.金融.电信等许多大型企业,解决困扰信息技术部门的备份管理问题.它在节省成本的前提下向您提供有保证的.自动.简单而且灵活的服务.Tivoli TSM 的管理架构,真正适合企业管理级管理需求,为企业提供高效.自动.可扩展的备份管理体系. TSM应用案例 在机房内,我们将在一台机器 (IBM RS/6000 服务器 ) 上安装 Tivoli T

VC++ 6.0 单步调试【写给自己看的调试总结帖】

写给自己看的调试总结帖 参考一: 先将光标移动到你需要停止的地方,点击一下工具栏中的小手工具,这个时候左边会有一个红色的圆点出现,然后点击"go F5"工具.程序会开始运行,直到运行到你设置的断点处停下来,这个时候你可以在下边的出口中检查你的变量的值 了.如果下面没有你需要的变量,你可以将变量名拖到变量窗口中. 如果你的变量窗口没有显示,你可以通过菜单-->查看-->调试窗口--->watch 打开它. 参考二: 逐过程调试-F10 逐语句调试-F11 跳到光标处-C

视频-上传文件怎么做到断点继传?

问题描述 上传文件怎么做到断点继传? 遇到项目中要上传视频的例子,请教大家,上传文件怎么做到断点继传? 解决方案 上传,如果用自己的服务端与客户端,做断点续传应该比较简单.需要做一个简单的上传数据库,再:断点续传的过程 ①断点续传需要在下载过程中记录每条线程的下载进度: ②每次下载开始之前先读取数据库,查询是否有未完成的记录,有就继续下载,没有则创建新记录插入数据库: ③在每次向文件中写入数据之后,在数据库中更新下载进度: ④下载完成之后删除数据库中下载记录. 解决方案二: 上传中断后,记录一个

chrome下的Grunt插件断点调试——基于node-inspector

之前调试grunt插件时,都是通过人肉打log来调试.不仅效率低,而且会产生一堆无用的代码.于是简单google了下node断点调试的方法,总结了下. 借助node-inspector,我们可以通过Chrome浏览器的调试工具来调试. 一.安装node-inspector npm install -g node-inspector   二.监听Nodejs的debug调试端口 node-inspector & 见到输出下面log,http://127.0.0.1:8080/debug?port=

VS2010“当前不会命中断点。还没有为该文档加载任何符号”寻觅终极解决方案

问题描述 问题如图中所示,在网上找了多种方法依旧无法解决,项目的的确确是在dubug模式下运行的,可有的代码就是无法被断点命中,调试起来诸多不便. 解决方案 解决方案二:关闭vs重新打开再试试.解决方案三:是附加到进程调试的时候出现的?那得重新再弄下,或者关闭在看下解决方案四:此问题源于我对自己做的项目的无知所致,之前是做j2ee开发的,公司几年前的项目需要升级,无奈在学校里学了些.net,就交给我升级,不料对.net确实有许多不懂的地方.以前发帖总是石沉帖海,这次有幸被回答,非常感谢!我的终极

学计算机的值得一看的文章,跟帖也很有水平啊

从csdn上转来的,n手货,原始作者大概是04年发表的,已经无从查找原文出处了. 希望纠结要不要读研的人,看到后有所帮助. 回复CSDN和KAOYAN诸位网友的几点看法,(为避免吵架,郑重声明,本人不是高手,只是有感而发的一点个人陋见,欢迎指正,事先感谢): 就我自己的理解,谈谈我对读研和软件学院的看法,不妥之处一笑了之即可. 如果你有实际开发工作经验,感觉自己的水平和实力进入了一个高原期,迫切需要从理论上提高,那么计算机学院是唯一选择.因为计算机学院才能让你在理论上更上一层楼.软件学院从教学计

c++ delete-C++ delete时出现了断点 我要怎么改

问题描述 C++ delete时出现了断点 我要怎么改 #include #include using namespace std; void main() { char *str1 = new char; char *str2 = new char; int num1, num2; int num; cout << "**********比较两个字符串大小************" << endl; cout << "输入两个字符串&qu

Xcode中的全局异常断点

一旦异常断点被添加,你可以鼠标右键选择 Edit Breakpoint 打开弹出菜单. 改变异常类型为Objective-C,这可以防止C++异常被捕获,你可能不想捕获这些. 因为通常情况下你的App中没有C++代码,而在OpenAL框架库和其他第三方代码可能会引发C++异常,但你不必处理这些.

转帖:PHP4(windows版本)中的COM函数

window|函数 这几天一直在写excel转化成mysql,发现一篇文章,搜一下phpx论坛,没有这个帖子,把它转帖如下: PHP4(windows版本)中的COM函数 介绍 内置于PHP4里的COM函数对于我们在win32环境下开发程序是相当有吸引力的,但是至今仍没有多少相关的技术文档.本文将以三个例子分 别处理 MS office 2000 Word . Excel . Adobe Distiller 来说明如何在PHP中使用COM函数. COM技术是由Microsoft在几年前提出并开发