InternetReadFile这个函数在网络断开或主机无响应时无法返回 程序在这种情况下CPU占100% , 请教这如何解决 ,谢谢! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 InternetReadFile就算占CPU也不可能这么夸张,应该是有死循环吧!! 这个函数可以用来下载文件或者读取网页源码使用。有办法避免你所说的问题。建议在使用该函数前先调用HttpQueryInfo取得头信息来决定网页是否能正常响应,于是你的问题解决。如果你是个懒人,希望我直接给你贴出代码。那么请你再加100分后并结贴给分,并说清楚你是取文件还是取网页源码。我给你贴出实现代码。 我是有获取两个网站的源码的,一个没问题,另一个就是卡在 InternetReadFile函数里(可能是这个网站服务器无反应,在网上查的) 那是你的错误认为而已。取源码的方式很多,但用InternetOpen和InternetReadFile确实是最稳定的方法,而且纯代码实现不依靠外部控件。我所采用的就是你所说的方法。你所遇到的问题我在两年前就遇到过。所以有针对性的在回你的贴子。这里说一下,delphi7在同时使用InternetOpen,InternetOpenURL,InternetCloseHandle,InternetReadFile四个函数时会被360杀毒软件报毒。另外InternetReadFile应该写在循环里多次读取,因为有些源码过多,一次性无法读完整。http://www.mwymwy.com/GetURLCode.rar这里给出一个dcu测试版本,完全解决你的问题,不会出现断开或无法响应而导致无法返回的问题。你可以像源码一样移植到其它程序中使用和编译,但并不是源码。源码需要你加分后才公开。 先谢谢你先,是这样的,我之前在请求头里没有加上Accept-Encoding: gzip, deflate,我猜测服务器以此识别客户是不是IE方式读数据,因此在段时间后就被踢出来了,现在加上后就没有这种情况了,但现在又多了一个新的问题,就是GZIP解压缩的问题,我用的是ZLIP,但总是报DATA ERROR的错误,不知这位朋友有没有遇到这种情况,望赐教,还有我这个贴真的是加不了分了,我的QQ 814207582 可以加,希望继续交流下去,谢谢了 我也用的是ZLIP,没用过GZI,所以你的后续问题我解决不了。抱歉。 现在发现是获取源码哪里出错了,我用IDHTTP获取的可以解压,但用internetreadfile获取的解压就出错,不知道是什么原因,我现在把源码贴出来吧function HttpGetString(mUrl , mReferer: string ; var mStringResult : string; mMethod : string;bGzip : boolean) : boolean;var hSession, hConnect, hRequest: hInternet; HostName, FileName, mData: String; f: File; Buf: Pointer; dwBufLen, dwIndex: DWord; Data: Array[0..1024] of Char;//Array[0..$400] of Char; TempStr: String; RequestMethod: PChar; InternetFlag: DWord; AcceptType: LPStr; mResult : boolean; mFileSize : integer; mBinaryData : boolean; BytesToRead, BytesReaded: DWord; p : integer; procedure ParseURL(URL: String; var HostName, FileName: String); //取得精确的服务器名字,和地址文件 //HTTP://<IP 地址>/[端口号]/[路径][?<查询信息>] procedure ReplaceChar(c1, c2: Char; var St: String); var p : Integer; begin while True do begin p := Pos(c1, St); if p = 0 then break else St[p] := c2; end; end; var i : Integer; begin if Pos('http://', LowerCase(URL)) <> 0 then System.Delete(URL, 1, 7); i := Pos('/', URL); HostName := Copy(URL, 1, i); FileName := Copy(URL, i, Length(URL) - i + 1); if (Length(HostName) > 0) and (HostName[Length(HostName)] = '/') then SetLength(HostName, Length(HostName) - 1); end; procedure CloseHandles; //5, 最后依次关闭request,connect,session句柄 begin InternetCloseHandle(hRequest); InternetCloseHandle(hConnect); InternetCloseHandle(hSession); end; begin try ParseURL(mUrl, HostName, FileName); //showmessage(HostName + ' ' + FileName); hSession := InternetOpen(PChar('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET4.0C)'), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0); hConnect := InternetConnect(hSession, PChar(HostName), INTERNET_DEFAULT_HTTP_PORT, PChar(''), PChar(''), INTERNET_SERVICE_HTTP, 0, 0); RequestMethod := PChar(mMethod);//('GET'); // InternetFlag := INTERNET_FLAG_RELOAD;//0; //是否取用缓存 InternetFlag := INTERNET_FLAG_RELOAD; AcceptType := PChar('*/*'); //接受类型 //3, 然后我们使用这个connect句柄来打开Http 请求得到一个HINTERNET request句柄; hRequest := HttpOpenRequest(hConnect, //通过InternetConnect()函数调用返回的HINTERNET类型的句柄 RequestMethod, //该参数是一个指向包含请求所使用的动词的字符串,如果为NULL,那么表示的是GET请求,可以选择有: //GET:接收服务器发送的数据 //POST:向服务器发送执行的操作 //HEAD:接收服务器对请求的响应标题 //DELETE:删除服务器上的一个资源 //PUT:为服务器发送存储信息 //LINK:在URL之间建立连接 PChar(FileName), //表示操作的对象,一般情况下为一个要接收的文件的文件名 'HTTP/1.1', //表示所使用的HTTP协议版本。NULL值表示HTTP/1.0 PChar(mReferer), //表示页的URL,lpszObjectName指定的信息存放在这个地址中 @AcceptType, //指定客户端可接受的信息类型。NULL则视为接收“text/*”类型,即文本类型 InternetFlag, //给出调用该函数的其他选项 0); //为异步I/O设置环境 //HttpAddRequestHeaders(hRequest, 'Accept-Language: zh-cn',length('Accept-Language: zh-cn'), HTTP_ADDREQ_FLAG_ADD or HTTP_ADDREQ_FLAG_REPLACE); HttpAddRequestHeaders(hRequest, 'Connection: Keep-Alive',length('Connection: Keep-Alive'), HTTP_ADDREQ_FLAG_ADD or HTTP_ADDREQ_FLAG_REPLACE); //HttpAddRequestHeaders(hRequest, 'Content-Type: application/x-www-form-urlencoded;charset=utf-8',length('Content-Type: application/x-www-form-urlencoded;charset=utf-8'), HTTP_ADDREQ_FLAG_ADD or HTTP_ADDREQ_FLAG_REPLACE); if bGZip = True then HttpAddRequestHeaders(hRequest, 'Accept-Encoding: gzip, deflate',length('Accept-Encoding: gzip, deflate'), HTTP_ADDREQ_FLAG_ADD or HTTP_ADDREQ_FLAG_REPLACE); HttpAddRequestHeaders(hRequest, 'x-requested-with: XMLHttpRequest',length('x-requested-with: XMLHttpRequest'), HTTP_ADDREQ_FLAG_ADD or HTTP_ADDREQ_FLAG_REPLACE); //Content-Type //4, 这时我们就可以使用这个request句柄来发送数据与读取从服务器返回的数据;//gzip, deflate HttpSendRequest(hRequest, //是HttpOpenRequest()函数调用返回的句柄 nil, //此参数用来指定发送时附加的头,这个标题和请求一起被发送 0, //标题的长度 nil, //指向待发送的数据 0); //待发送数据的长度 dwIndex := 0; dwBufLen := 1024; GetMem(Buf, dwBufLen); //获取服务器对请求的响应信息 mResult := HttpQueryInfo(hRequest, //是HttpOpenRequest()函数调用返回的句柄 HTTP_QUERY_RAW_HEADERS_CRLF,//HTTP_QUERY_CONTENT_LENGTH, //指定返回信息及返回的方式 (返回文件的大小) Buf, //存放返回信息(指针) dwBufLen, //返回信息的长度 dwIndex); //存放下一个匹配的标题索引值,如果找不到匹配的标题,那么此值将返回:ERROR_HTTP_HEADER_NOT_FOUND Form1.Memo3.Lines.Add(PChar(Buf)); mData := PChar(Buf); p := pos('X-Last-Serial:',mData); if p <> 0 then begin system.Delete(mData,1,p+length('X-Last-Serial:')-1); pos('Content-Type:',mData); mData := Trim(copy(mData,1,pos('Content-Type:',mData)-1)); s_A_SerialID := mData; end; mResult := HttpQueryInfo(hRequest, //是HttpOpenRequest()函数调用返回的句柄 HTTP_QUERY_CONTENT_LENGTH, //指定返回信息及返回的方式 (返回文件的大小) Buf, //存放返回信息(指针) dwBufLen, //返回信息的长度 dwIndex); mBinaryData := false; if mResult or not mBinaryData then begin //mFileSize := StrToInt(StrPas(Buf)); //把文件长度付给FTFileSize 无用? BytesReaded := 0; mStringResult := ''; //Form1.Memo3.Lines.Add('********************'); while True do //死循环,不断读取网络文件数据 begin BytesToRead := 1024; //Form1.Memo3.Lines.Add('********ReadFile********'); if not InternetReadFile(hRequest,@Data,1024,BytesToRead) then begin mResult := False; Break; //如果网络读取字节流不成功,则退出循环 end else begin //Form1.Memo3.Lines.Add('********EndFile********'); if BytesToRead = 0 then begin mResult := False; Break; //如果读取数据为0,则跳出循环 end else begin TempStr := Data; SetLength(TempStr,BytesToRead); mStringResult := mStringResult + TempStr; inc(BytesReaded,BytesToRead); //保存已经读取的总字节数 //Form1.Memo3.Lines.Add(FloatToStr(BytesToRead)+' '+FloatToStr(BytesReaded)); end; end; end; SetLength(mStringResult, BytesReaded); //设置变量FTStringResult大小, mResult := BytesReaded <> 0; //保存结果 end; //Form1.Memo3.Lines.Add('********END********'); Result := mResult; FreeMem(Buf); //释放内存 CloseHandles; except mResult := false; Result := mResult; //Form1.Memo3.Lines.Add(mUrl + '出错了'); end; end 可能是你的internetreadfile没把文件读完整,或漏掉几个字节。导致的问题。 小问题 给存储过程参数赋值 ★★happy birthday to lw549 boolean缺省值居然是true,一直以为是false呢~! ADOQUery 用SQL出错 一个查询的数据集结果,如何一下定位到指定的那一行,不通过循环? 帮忙,我个关于全局变量的问题。 请教一下:同一程序同一图同截的大小地方都是一样的,为什么大小就是不一样呢? 菜题,DELPHI如何连接EXCEL? 搞了一天也没解决,上来请教 SQL 如何按多个字段分类? delphi中如何显示tif格式图片
建议在使用该函数前先调用HttpQueryInfo取得头信息来决定网页是否能正常响应,于是你的问题解决。如果你是个懒人,希望我直接给你贴出代码。那么请你再加100分后并结贴给分,并说清楚你是取文件还是取网页源码。我给你贴出实现代码。
我是有获取两个网站的源码的,一个没问题,另一个就是卡在 InternetReadFile函数里(可能是这个网站服务器无反应,在网上查的)
这里给出一个dcu测试版本,完全解决你的问题,不会出现断开或无法响应而导致无法返回的问题。你可以像源码一样移植到其它程序中使用和编译,但并不是源码。源码需要你加分后才公开。
先谢谢你先,是这样的,我之前在请求头里没有加上Accept-Encoding: gzip, deflate,我猜测服务器以
此识别客户是不是IE方式读数据,因此在段时间后就被踢出来了,现在加上后就没有这种情况了,但现在又
多了一个新的问题,就是GZIP解压缩的问题,我用的是ZLIP,但总是报DATA ERROR的错误,不知这位朋友
有没有遇到这种情况,望赐教,还有我这个贴真的是加不了分了,我的QQ 814207582 可以加,希望继续交
流下去,谢谢了
现在发现是获取源码哪里出错了,我用IDHTTP获取的可以解压,但用internetreadfile获取的解压就出错,不知道是什么原因,我现在把源码贴出来吧function HttpGetString(mUrl , mReferer: string ; var mStringResult : string; mMethod : string;bGzip : boolean) : boolean;
var
hSession, hConnect, hRequest: hInternet;
HostName, FileName, mData: String;
f: File;
Buf: Pointer;
dwBufLen, dwIndex: DWord;
Data: Array[0..1024] of Char;//Array[0..$400] of Char;
TempStr: String;
RequestMethod: PChar;
InternetFlag: DWord;
AcceptType: LPStr;
mResult : boolean;
mFileSize : integer;
mBinaryData : boolean;
BytesToRead, BytesReaded: DWord;
p : integer; procedure ParseURL(URL: String; var HostName, FileName: String); //取得精确的服务器名字,和地址文件
//HTTP://<IP 地址>/[端口号]/[路径][?<查询信息>]
procedure ReplaceChar(c1, c2: Char; var St: String);
var
p : Integer;
begin
while True do
begin
p := Pos(c1, St);
if p = 0 then
break
else
St[p] := c2;
end;
end; var
i : Integer;
begin
if Pos('http://', LowerCase(URL)) <> 0 then
System.Delete(URL, 1, 7);
i := Pos('/', URL);
HostName := Copy(URL, 1, i);
FileName := Copy(URL, i, Length(URL) - i + 1); if (Length(HostName) > 0) and (HostName[Length(HostName)] = '/') then
SetLength(HostName, Length(HostName) - 1);
end; procedure CloseHandles; //5, 最后依次关闭request,connect,session句柄
begin
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hSession);
end; begin
try
ParseURL(mUrl, HostName, FileName);
//showmessage(HostName + ' ' + FileName);
hSession := InternetOpen(PChar('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET4.0C)'), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
hConnect := InternetConnect(hSession, PChar(HostName), INTERNET_DEFAULT_HTTP_PORT, PChar(''), PChar(''), INTERNET_SERVICE_HTTP, 0, 0);
RequestMethod := PChar(mMethod);//('GET'); //
InternetFlag := INTERNET_FLAG_RELOAD;//0; //是否取用缓存 InternetFlag := INTERNET_FLAG_RELOAD;
AcceptType := PChar('*/*'); //接受类型
//3, 然后我们使用这个connect句柄来打开Http 请求得到一个HINTERNET request句柄;
hRequest := HttpOpenRequest(hConnect, //通过InternetConnect()函数调用返回的HINTERNET类型的句柄
RequestMethod, //该参数是一个指向包含请求所使用的动词的字符串,如果为NULL,那么表示的是GET请求,可以选择有:
//GET:接收服务器发送的数据
//POST:向服务器发送执行的操作
//HEAD:接收服务器对请求的响应标题
//DELETE:删除服务器上的一个资源
//PUT:为服务器发送存储信息
//LINK:在URL之间建立连接
PChar(FileName), //表示操作的对象,一般情况下为一个要接收的文件的文件名
'HTTP/1.1', //表示所使用的HTTP协议版本。NULL值表示HTTP/1.0
PChar(mReferer), //表示页的URL,lpszObjectName指定的信息存放在这个地址中
@AcceptType, //指定客户端可接受的信息类型。NULL则视为接收“text/*”类型,即文本类型
InternetFlag, //给出调用该函数的其他选项
0); //为异步I/O设置环境
//HttpAddRequestHeaders(hRequest, 'Accept-Language: zh-cn',length('Accept-Language: zh-cn'), HTTP_ADDREQ_FLAG_ADD or HTTP_ADDREQ_FLAG_REPLACE);
HttpAddRequestHeaders(hRequest, 'Connection: Keep-Alive',length('Connection: Keep-Alive'), HTTP_ADDREQ_FLAG_ADD or HTTP_ADDREQ_FLAG_REPLACE);
//HttpAddRequestHeaders(hRequest, 'Content-Type: application/x-www-form-urlencoded;charset=utf-8',length('Content-Type: application/x-www-form-urlencoded;charset=utf-8'), HTTP_ADDREQ_FLAG_ADD or HTTP_ADDREQ_FLAG_REPLACE);
if bGZip = True then
HttpAddRequestHeaders(hRequest, 'Accept-Encoding: gzip, deflate',length('Accept-Encoding: gzip, deflate'), HTTP_ADDREQ_FLAG_ADD or HTTP_ADDREQ_FLAG_REPLACE);
HttpAddRequestHeaders(hRequest, 'x-requested-with: XMLHttpRequest',length('x-requested-with: XMLHttpRequest'), HTTP_ADDREQ_FLAG_ADD or HTTP_ADDREQ_FLAG_REPLACE);
//Content-Type
//4, 这时我们就可以使用这个request句柄来发送数据与读取从服务器返回的数据;//gzip, deflate
HttpSendRequest(hRequest, //是HttpOpenRequest()函数调用返回的句柄
nil, //此参数用来指定发送时附加的头,这个标题和请求一起被发送
0, //标题的长度
nil, //指向待发送的数据
0); //待发送数据的长度 dwIndex := 0;
dwBufLen := 1024;
GetMem(Buf, dwBufLen);
//获取服务器对请求的响应信息
mResult := HttpQueryInfo(hRequest, //是HttpOpenRequest()函数调用返回的句柄
HTTP_QUERY_RAW_HEADERS_CRLF,//HTTP_QUERY_CONTENT_LENGTH, //指定返回信息及返回的方式 (返回文件的大小)
Buf, //存放返回信息(指针)
dwBufLen, //返回信息的长度
dwIndex); //存放下一个匹配的标题索引值,如果找不到匹配的标题,那么此值将返回:ERROR_HTTP_HEADER_NOT_FOUND
Form1.Memo3.Lines.Add(PChar(Buf));
mData := PChar(Buf);
p := pos('X-Last-Serial:',mData);
if p <> 0 then
begin
system.Delete(mData,1,p+length('X-Last-Serial:')-1);
pos('Content-Type:',mData);
mData := Trim(copy(mData,1,pos('Content-Type:',mData)-1));
s_A_SerialID := mData;
end;
mResult := HttpQueryInfo(hRequest, //是HttpOpenRequest()函数调用返回的句柄
HTTP_QUERY_CONTENT_LENGTH, //指定返回信息及返回的方式 (返回文件的大小)
Buf, //存放返回信息(指针)
dwBufLen, //返回信息的长度
dwIndex);
mBinaryData := false;
if mResult or not mBinaryData then
begin
//mFileSize := StrToInt(StrPas(Buf)); //把文件长度付给FTFileSize 无用?
BytesReaded := 0;
mStringResult := '';
//Form1.Memo3.Lines.Add('********************');
while True do //死循环,不断读取网络文件数据
begin
BytesToRead := 1024;
//Form1.Memo3.Lines.Add('********ReadFile********');
if not InternetReadFile(hRequest,@Data,1024,BytesToRead) then
begin
mResult := False;
Break; //如果网络读取字节流不成功,则退出循环
end
else
begin
//Form1.Memo3.Lines.Add('********EndFile********');
if BytesToRead = 0 then
begin
mResult := False;
Break; //如果读取数据为0,则跳出循环
end
else
begin
TempStr := Data;
SetLength(TempStr,BytesToRead);
mStringResult := mStringResult + TempStr;
inc(BytesReaded,BytesToRead); //保存已经读取的总字节数
//Form1.Memo3.Lines.Add(FloatToStr(BytesToRead)+' '+FloatToStr(BytesReaded));
end;
end;
end;
SetLength(mStringResult, BytesReaded); //设置变量FTStringResult大小,
mResult := BytesReaded <> 0; //保存结果
end;
//Form1.Memo3.Lines.Add('********END********');
Result := mResult;
FreeMem(Buf); //释放内存
CloseHandles;
except
mResult := false;
Result := mResult;
//Form1.Memo3.Lines.Add(mUrl + '出错了');
end;
end