Tidhttpserver - eidconnclosed قبل إرسال رد إلى المنشور
-
26-09-2019 - |
سؤال
أواجه مشكلة في تطبيق خادم HTTP مع Indy 10 في Delphi 2007.
لقد قمت بإعداد معالج حدث بسيط لحدث CommandGet.
عند الرد على البيانات المرسلة باستخدام طريقة GET ، يمكنني تحليل params وإرسال بيانات XML مع عدم وجود مشاكل. (انظر الرمز أدناه)
Download := ARequestInfo.Params.Values['dld'];
Config := ARequestInfo.Params.Values['config'];
Flash := ARequestInfo.Params.Values['flash'];
Employees := ARequestInfo.Params.Values['employees'];
Schedule := ARequestInfo.Params.Values['schedules'];
AppTables := ARequestInfo.Params.Values['apptables'];
Heartbeat := NewHeartbeat;
Heartbeat.Version.Dld := Download;
Heartbeat.Version.Config := Config;
Heartbeat.Version.Flash := Flash;
Heartbeat.Version.Employee := Employees;
Heartbeat.Version.Schedule := Schedule;
Heartbeat.Version.AppTables := AppTables;
AResponseInfo.ContentType := 'application/xml';
AResponseInfo.ResponseNo := 200;
AResponseInfo.ContentText := '<?xml version="1.0" encoding="utf-8"?>' +
#13+#10 + FormatXMLData(Heartbeat.XML);
عندما أحاول الرد على البيانات التي يتم إرسالها باستخدام منشور ، لا يتم إرسال الاستجابة بواسطة Indy ، بدلاً من ذلك ، يتم رفع eidconnclosedgrace بشكل قاطع بواسطة TidioHandler.Writedirect تشكيل خط checkfordisconnect (الحقيقي ، الحقيقي). إليكم كيف أتعامل مع بيانات النشر الواردة
XMLDocument1.xml.Clear;
XMLDocument1.Active := True;
XMLDocument1.XML.text := ARequestInfo.FormParams;
SynMemo1.Lines.Add(ARequestInfo.FormParams);
SynMemo1.Lines.Add(#13+#10);
if XMLDocument1.XML.Count > 0 then
begin
XMLDocument1.XML.Delete(0);
XMLDocument1.XML.Delete(0);
for i := pred(xmldocument1.xml.count) downto 0 do
begin
stmp := XMLDocument1.XML.Strings[i];
if Length(stmp) > 0 then
begin
if Copy(stmp,1,1) = '<' then
break
else
XMLDocument1.XML.Delete(i);
end
else
XMLDocument1.XML.Delete(i);
end;
XMLDocument1.XML.Text := StringReplace(XMLDocument1.XML.Text,
'<Punches ', '<Punches xmlns="http://ats/punch" ', [rfReplaceAll]);
end;
Punch := GetPunches(XMLDocument1);
PunchReply := NewOperationStatus;
PunchReply.Uid := Punch.Uid;
PunchReply.NodeValue := 'OK';
stmp := '<?xml version="1.0" encoding="utf-8"?>' +
#13+#10 + FormatXMLData(PunchReply.XML);
SynMemo1.Lines.Add(stmp);
SynMemo1.Lines.Add(#13+#10);
AResponseInfo.ContentType := 'text/html';
AResponseInfo.ContentStream := TStringStream.Create(stmp);
لقد استخدمت Wireshark لمعرفة ما يحدث ويبدو أن Indy ترسل ACK مرة أخرى قبل إرسال الاستجابة والتسبب في فصل العميل.
لاختبار هذا ، قمت بإعداد Apache مع PHP وكتبت برنامج نصي PHP للقيام بنفس المهمة وكل شيء يعمل بشكل جيد ، والفرق هو أن البيانات المنشورة يتم الرد عليها بمحتوى الاستجابة وليس ACK.
أي اقتراحات حول كيفية حل هذا حتى أستجيب لبيانات النشر وكذلك الحصول على.
أنا عالق مع هذا الآن ، كما ترون من تتبع Wireshark هذا (انقر على الرابط للصورة) لقد زادت المهلة إلى 20 ثانية. وما زالت لا تعمل. سأقوم ببعض التحقيقات. وانظر ما يمكنني اكتشافه. يبدو وكأنه إندي يعتقد أن الانفصال قد حدث قبل أن يكون
المحلول
يبدو أن HTTP يتم إرسالها كـ
Transfer-Encoding: chunked
لذلك لا يوجد طول محتوى. لكن إصدار Indy الذي أستخدمه لا يدعم هذا الوضع.
نصائح أخرى
لا يتم إرسال ACKS بواسطة Indy نفسها ، ولكن من خلال المقبس الأساسي بدلاً من ذلك ، وحتى بعد ذلك فقط في الرد على الحزم المستلمة من الطرف الآخر. يعني Eidconnclosdgrace أن العميل يفصل المقبس عن عمد في نهايته قبل أن يتمكن الخادم من إرسال بيانات الرد الخاصة به. حقيقة أن ACK موجود يساعد على إثبات أن (من المحتمل أن يكون المقبس هو حزمة زعانف العميل أثناء الانفصال).