delphi - How to avoid getting an error 10053 (WSAECONNABORTED) if a HttpGet operation in Android is lasting too long? -
i have android application communicating delphi 2006 web service application using indy 10 tidhttpserver (coming delphi 2006). delphi application generates big xml file , serves this. xml generation may last more 5 minutes.
if duration of generatexml()
more 5 minutes (*), detect error 10053 in tidhttpresponseinfo.writecontent
if running in delphi ide:
socket error # 10053 software caused connection abort.
however, on android side nothing detected , httpget
-call lasts forever.
my questions are:
1.) why error 10053 , how can avoid it? seems android times out connection, http.socket.timeout
set infinite.
and
2.) can detect such error on client side (other setting timeout, have big useful)? can in tidhttpserver.onexception?
here code. android - download function, run inside asynctask:
protected static httpentity downloadentity(string url) throws ioexception { httpclient client = new defaulthttpclient(); //check because of error 10053: timeout null -> infinite log.d("tag", "http.socket.timeout: " + client.getparams().getparameter("http.socket.timeout")); httpget = new httpget(url); httpresponse response; try { //in case of error 10053 following call seems last forever (in plainsocketimpl.read) response = client.execute(get); } catch (clientprotocolexception e) { //... } //... return response.getentity(); }
delphi implementation of tidhttpserver.oncommandget:
procedure servexmldoc(xmldoc: ixmldocument; responseinfo: tidhttpresponseinfo); var tempstream: tmemorystream; begin responseinfo.contenttype := 'text/xml'; tempstream := tmemorystream.create; xmldoc.savetostream(tempstream); responseinfo.freecontentstream := true; responseinfo.contentstream := tempstream; end; procedure tmyservice.httpservercommandget(acontext: tidcontext; requestinfo: tidhttprequestinfo; responseinfo: tidhttpresponseinfo); begin coinitialize(nil); try //... servexmldoc(generatexml(), responseinfo); couninitialize; end; end;
edit: (*) have done further testing , experienced error in cases whole process had duration of under 2 minutes.
something between android , server, such firewall/router, cutting connection after idle long. should try enabling tcp keep-alives avoid that.
on other hand, kind of situation http 1.1's chunked transfer encoding designed handle (assuming using http 1.1 begin with). instead of waiting 5 minutes entire xml generated in full before sending client, should send xml in pieces being generated. not keep connection active, reduces server's memory footprint since doesn't have store entire xml in memory @ 1 time.
tidhttpserver
not (yet) natively support sending chunked responses (but tidhttp
support receiving chunked responses), not difficult implement manually. write custom tstream
derived class , overwrite virtual write()
method (or use indy's tideventstream
class) write data http client using format outlined in rfc 2616 section 3.6.1. that, can have servexmldoc()
set responseinfo.transferencoding
property 'chunked'
, call responseinfo.writeheader()
method without setting either responseinfo.contenttext
or responseinfo.contentstream
properties, pass custom stream ixmldocument.savetostream()
finish writing response data after headers. example:
type tmychunkedstream = class(tstream) private fio: tidiohandler; public constructor create(aio: tidiohandler); function write(const buffer; count: longint): longint; override; procedure finished; ... end; constructor tmychunkedstream.create(aio: tidiohandler); begin inherited create; fio := aio; end; function tmychunkedstream.write(const buffer; count: longint): longint; override; begin if count > 0 begin fio.writeln(inttohex(count, 1)); fio.write(rawtobytes(buffer, count)); fio.writeln; end; result := count; end; procedure tmychunkedstream.finished; begin fio.writeln('0'); fio.writeln; end;
procedure servexmldoc(xmldoc: ixmldocument; responseinfo: tidhttpresponseinfo); var tempstream: tmychunkedstream; begin responseinfo.contenttype := 'text/xml'; responseinfo.transferencoding := 'chunked'; responseinfo.writeheader; tempstream := tmychunkedstream.create(responseinfo.connection.iohandler); try xmldoc.savetostream(tempstream); tempstream.finished; tempstream.free; end; end;
if, on other hand, bulk of waiting inside of generatexml()
, not in xmldoc.savetostream()
, need rethink server design, , figure out way speed generatexml()
, or rid of ixmldocument
, create xml manually can send using responseinfo.connection.iohandler
creating xml content.
Comments
Post a Comment