سؤال

لدي تطبيق عميل يجب إرسال رسائل إعلانية إلى تطبيق خادم اختياري. لا ينبغي أن يتأثر العميل بما إذا كان فتح خادم الخادم أم لا. يجب أن تحاول الاتصال بتطبيق الخادم وإرسال رسالة إخطار، وفي حالة وجود أخطاء، يجب أن تجاهل بصمت بشكل صامت جميع الأخطاء ومتابعة العمل.

أنا أستخدم Indy لتواصل TCP ولكن جميع محاولات تجنب رسائل الخطأ التي تظهر (أي متى يغلق تطبيق الخادم أثناء الاتصال بالعميل).

هل هناك طريقة لجعل هذا القوي حقا؟

الكود الحالي يشبه هذا:

if (not Client.Connected) then
  begin
  Client.Host := ServerName;
  Client.Port := ServerPort;
  Client.ConnectTimeout := ConnectTimeout;
  try
    Client.Connect;
  except
    Exit;
  end;
  end
try
  Client.IOHandler.WriteLn ('NOTIFYCHANGE "' + Param + '"');
  Client.IOHandler.WriteBufferFlush;
except
  try
    Client.Disconnect;
  except
    { ignore errors while disconnecting }
  end;
  try
    Client.Connect;
  except
    { ignore errors while connecting }
  end;
end;
هل كانت مفيدة؟

المحلول

هل حقا الحصول على رسائل الخطأ من لك برنامج؟ من الشائع أن تصحيح الأخطاء التي يكتشفها المصحح استثناءات ويقاطع برنامجك، وبعض الناس يخلطون من رسالة مصحح الأخطاء للحصول على رسالة من برنامجهم الخاص. هل أنت متأكد من أن هذا ليس هو الحال هنا؟ لقد كتبت عن هذا الوضع من قبل. إليك ملخص طرق لتجنب ذلك:

  • استخدم "نقاط التوقف المتقدمة" لتعطيل سلوك اعتراض مصحح الأخطاء في منطقة التعليمات البرمجية.
  • تكوين المصحح لتجاهل فئات معينة من الاستثناءات. (هذا يشعر بأنه شائع بشكل خاص مع Indy لأنه يميل إلى إلقاء استثناءات العديد من الاستثناءات.)
  • اضبط المصحح على عدم مقاطعة البرنامج أبدا على الاستثناءات.
  • تعطيل تصحيح الأخطاء المتكاملة تماما.

إذا كانت الرسالة تأتي حقا من برنامجك وليس المصحح، فارجع استعمال المصحح لمعرفة أين تأتي الرسالة من. عندما تظهر الرسالة، توقف البرنامج مؤقتا وإلقاء نظرة على نافذة المكدس المكالمات للعثور على مساحة التعليمات البرمجية التي تعرض الرسالة، لأنه من الواضح أنه ليس في التعليمات البرمجية التي أظهرتها. يتم قمع الكود الذي أظهرته جيدا (وليس التعامل مع جميع الاستثناءات، حتى تلك التي لا ترتبط Indy، مثل EAccessViolation و EOutOfMemory.

نصائح أخرى

للحصول على مهمة اتصالات TCP بسيطة استخدمتها تشابك عصبى الحزمة، إنها ليست مخادئة مثل Indy ويشعر بأنها "نظافة" لاستخدامها.

من الرمز الأخير:

procedure SendMessage(m: string);
var
  sock : TTCPBlockSocket;
  response : string;
begin
  Sock := TTCPBlockSocket.Create;
  try
    Sock.SetTimeout(200);
    Sock.Connect(PrinterServerAddr, IntToStr(PrinterServerPort));

    Sock.SendString(m);
    response := Sock.RecvString(1000);
  finally
    Sock.Free;
  end;
end;

..
try
  SendMessage(NewMessage);
except
 //..handle exception..
end;

لف ذلك داخل TTHREAT إذا كنت ترغب في تجنب حظر خيطك الحالي.

إذا كان ذلك ممكنا، فكر في استخدام UDP. هذا "بدون اتصال"، لذلك سوف يرسل المرسل فقط الرسالة وسيتم تلقي تطبيق الاستقبال إذا كان الاستماع إلى المنفذ. ومع ذلك، لا يحصل المرسل على أي تأكيد بشأن التسليم ما لم يرسل الخادم نوعا ما من الاعتراف.

استجابة Harriv على ما يرام، فأنت تصف سلوك اتصال UDP. أنا أستخدم في موقف مماثل.

أنت لا تقول ما إذا كنت تستخدم Indy 9 أو 10. أستخدم 9، بنفسي، لذلك يفترض أدناه هذا.

لماذا ليس هذا فقط؟:

procedure Send(Target: String; Port: Integer; S: String);
var
  C: TIdTcpClient;
begin
  C := TIdTcpClient.Create(nil);
  try
    try
      C.Host := Target;
      C.Port := Port;
      C.Connect;
      try
        C.Write(S);
      finally
        C.Disconnect;
      end;
    except
      // Ignore Indy exceptions
      on EIdException do;
    end;
  finally
    C.Free;
  end;
end;

من السهل بما يكفي لتحويل هذا إلى إجراء يستخدم TITTCPClient موجود مسبقا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top