使用Indy的TIdHTTP
组件开发HTTP客户端时遇到问题。我正在使用Indy 10.5.9.0。
当我调用TIdHTTP.DoRequest()
方法时,组件会冻结,并引发异常:
连接正常关闭
我已尝试使用TIdHTTP.Post()
方法,但同样的问题也会发生。
使用TIdHTTP.Get()
方法不会发生问题。
这是我的代码:
try
jsonLatestFirmware := TJSONObject.ParseJSONValue(httpClient.Get(strGetLatest)) as TJSONObject;
try
srv := 'http://' + currentAlive.IP + ':9335/upgrade?command=start';
sList := TStringList.Create;
sList.Text := jsonLatestFirmware.get('data').JsonValue.ToString;
fileName := ExtractFilePath(Application.ExeName) + 'finals\' + currentMACQR + '-' + currentAlive.IP + '.json';
sList.SaveToFile(fileName);
JsonRetorno := TStringStream.Create('');
try
JsonToSend := TStringStream.Create;
WriteStringToStream(JsonToSend,TIdHTTPAccess(httpClient).SetRequestParams(sList, TEncoding.UTF8));
JsonToSend.Position := 0;
TIdHTTPAccess(httpClient).DoRequest('POST',srv,JsonToSend,jsonRetorno,[]); //component freezes here...
strRetorno := TStringList.Create();
strRetorno.LoadFromStream(JsonRetorno);
lblInformacao.Visible := True;
ShowMessage(strRetorno.Text);
except
on E: Exception do
ShowMessage('Error on request: '#13#10 + E.Message);
end;
finally
sList.Free;
JsonRetorno.Free;
JsonToSend.Free;
jsonResponse.Free;
end;
except
on E: Exception do
ShowMessage('There are no firmwares available for this product.');
end;
任何人都可以帮我解决这个问题吗?
答案 0 :(得分:2)
我正在使用Indy 10.5.9.0。
这是一个非常陈旧且过时的版本。在撰写本文时,最新版本是10.6.2.5455。 Please upgrade,因为10.5.9以来对Indy进行了很多修改和修复。
当我调用
TIdHTTP.Post()
方法时,组件会冻结,并引发异常:
首先,您没有致电TIdHTTP.Post()
,而是致电TIdHTTP.DoRequest()
。您应该拨打TIdHTTP.Post()
,而在内部为您调用TIdHTTP.DoRequest()
:
httpClient.Post(srv, JsonToSend, jsonRetorno);
其次,Post()
无法同时冻结并引发异常。实际上发生了什么?你发布的JSON有多大?服务器是否在引发异常之前发送任何类型的响应?
第三,你绝对根本不应该调用TIdHTTP.SetRequestParams()
。当TStrings
以#{1}}格式提交HTML网络表单时,该方法仅供TIdHTTP.Post()
重载版application/x-www-webform-urlencoded
内部使用。这不是你在这种情况下所需要的。您需要按原样发布JSON,而不是对其进行webform编码。
Indy使用阻塞套接字。 Indy的大多数操作都是同步的。 TIdHTTP.Post()
也不例外。它阻止调用线程,直到HTTP帖子完成。如果它冻结,这意味着帖子需要很长时间才能发送,或者服务器没有发回有效的响应。如果TIdHTTP.Post()
引发“正常关闭连接”异常,则意味着服务器已在其TIdHTTP
仍通过套接字发送/读取数据时关闭了套接字连接。例如,如果服务器不喜欢您的POST
请求,或者它确定JSON在接收时无效,则可能发生这种情况。
此外,您的代码通常可以简化。您正在滥用TStringList
来处理JSON数据。
尝试更像这样的东西:
var
sJSON, sRetorno: string;
jsonLatestFirmware: TJSONValue;
JsonToSend: TStringStream;
...
begin
...
try
sJSON := httpClient.Get(strGetLatest);
except
ShowMessage('There are no firmwares available for this product.');
Exit;
end;
try
jsonLatestFirmware := TJSONObject.ParseJSONValue(sJSON);
try
sJson := (jsonLatestFirmware as TJSONObject).get('data').JsonValue.ToString;
finally
jsonLatestFirmware.Free;
end;
JsonToSend := TStringStream.Create(sJson, TEncoding.UTF8);
try
JsonToSend.SaveToFile(ExtractFilePath(Application.ExeName) + 'finals\' + currentMACQR + '-' + currentAlive.IP + '.json');
httpClient.Request.ContentType := 'application/json';
sRetorno := httpClient.Post('http://' + currentAlive.IP + ':9335/upgrade?command=start', JsonToSend);
finally
JsonToSend.Free;
end;
except
on E: Exception do
ShowMessage('Error: '#13#10 + E.Message);
Exit;
end;
lblInformacao.Visible := True;
ShowMessage(sRetorno);
...
end;