التحقق من اتصالات المقبس في دلفي. دلفي. مآخذ البرمجة في دلفي. إرسال واستقبال البيانات المعقدة

المقابس (من المقبس (الإنجليزية) - الموصل، المقبس) هي واجهة البرنامج، وتوفير تبادل المعلومات بين العمليات.

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

ومن المهم التمييز بين نوعين من المقابس: مآخذ العميل ، و مآخذ الخادم .

للعمل مع نوع المقابس "العميل" في دلفي، يوجد مكون TClientSocket، يمكنك العمل مع مآخذ التوصيل "الخادم" باستخدام المكون TServerSocket.

تركيب المكونات

في كثير من الأحيان لا يتم تضمين مكونات TServerSocket وTClientSocket في حزمة تثبيت دلفي القياسية، ولكن يمكن تثبيتها بشكل إضافي.

انتقل إلى علامة تبويب مكونات "الإنترنت" وتحقق من وجود مكونات TServerSocket وTClientSocket هناك؛ وإذا لم يكن الأمر كذلك، فقم بتثبيتها. انتقل إلى قائمة "حزم المكونات/التثبيت"، ثم انقر فوق الزر "إضافة". في مربع الحوار الذي يفتح، تحتاج إلى العثور على الملف "dclsocketsXX.bpl" (وهو موجود في مجلد bin، الموجود في مجلد دلفي)، حيث XX هو رقم الإصدار الرقمي لدلفي الخاص بك. حدد موقع الملف، وانقر فوق فتح، ثم في نافذة تثبيت الحزم، انقر فوق موافق. الآن ظهر مكونان في علامة التبويب "الإنترنت" - TServerSocket وTClientSocket.

العمل مع مآخذ العميل (tClientSocket)

1) تحديد خصائص المنفذ والمضيف.لخصائص الاتصال الناجح ميناءو يستضيفيحتاج مكون TClientSocket إلى تعيين بعض القيم. في خاصية المنفذ، تحتاج إلى تحديد رقم المنفذ للاتصال (1 – 65535، لكن من الأفضل أخذه من النطاق 1001 – 65535، لأن الأرقام التي تصل إلى 1000 قد تكون مشغولة بخدمات النظام).

يستضيف- اسم المضيف أو عنوان IP للكمبيوتر الذي تريد الاتصال به. على سبيل المثال، rus.delphi.com أو 192.128.0.0.

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

3) إرسال/استقبال البيانات.

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

الخصائص الأساسية لمكون TClientSocket

يشير إلى ما إذا كان المقبس مفتوحًا أم مغلقًا. مفتوح – صحيح، مغلق – خطأ. متاح للتسجيل.

اسم المضيف للاتصال به

عنوان IP الخاص بالكمبيوتر الذي تريد الاتصال به. على عكس المضيف، يمكن تحديد IP فقط هنا. والفرق هو أنه إذا قام المضيف بتحديد الاسم الأبجدي للكمبيوتر، فسيتم طلب عنوان IP من DNS

رقم منفذ الكمبيوتر للاتصال به (1-65535)

نوع العميل

يحتوي على نوع نقل البيانات:

ctBlocking- الإرسال المتزامن ( على القراءةو OnWriteلا يعمل). نوع الاتصال المتزامن مناسب لتبادل البيانات المتدفقة؛

ctNonBlocking- الإرسال غير المتزامن (يمكن إرسال/استقبال البيانات باستخدام الأحداث على القراءةو OnWrite)

الطرق الأساسية لمكون TClientSocket

فتح مأخذ توصيل (ضبط الخاصية النشطة على True)

إغلاق المقبس (ضبط الخاصية النشطة على False)

الأحداث الرئيسية لمكون TClientSocket

عند الاتصال

يحدث عند إنشاء اتصال. في المعالج، يمكنك الآن بدء التفويض أو إرسال/استقبال البيانات

عند الاتصال

يحدث أيضًا عند الاتصال. يختلف عن OnConnect في أنه لم يتم إنشاء الاتصال بعد. غالبا ما تستخدم، على سبيل المثال، لتحديث الحالة

عند قطع الاتصال

يحدث هذا الحدث عندما يتم إغلاق المقبس بواسطة البرنامج أو الكمبيوتر البعيد أو بسبب فشل

يقع الحدث عندما يكون هناك خطأ. أثناء فتح مأخذ التوصيل، لن يساعد هذا الحدث في اكتشاف الخطأ. لتجنب ظهور رسالة خطأ من Windows، من الأفضل الاهتمام بمعالجة الاستثناءات الداخلية عن طريق وضع البيانات المفتوحة في كتلة " حاول..إلا »

OnLookup

يحدث الحدث عند محاولة الحصول على عنوان IP من DNS

يحدث هذا الحدث عندما يرسل لك جهاز كمبيوتر بعيد أي بيانات. عند الاتصال بـ OnRead، من الممكن معالجة البيانات المستلمة

يحدث هذا الحدث عندما يُسمح لبرنامجك بكتابة البيانات إلى المقبس

ستناقش هذه المقالة الخصائص والوظائف الأساسية مكونات دلفي: TClientSocket و TServerSocket – يستخدمان للعمل مع الشبكة باستخدام بروتوكول TCP\IP.

انتباه!إذا كنت تستخدم نسخة من دلفي أعلى من 6.0، فأنت بحاجة أولاً إلى تثبيت مكونات المقبس؛ في جميع إصدارات دلفي يتم ذلك كما يلي:

  • انتقل إلى مربع حوار تثبيت الحزم...: (القائمة الرئيسية) المكون -> تثبيت الحزم؛
  • انقر فوق الزر "إضافة..."، وبعد ذلك نجد مجلد Bin الخاص بـ Delphi الخاص بك (على سبيل المثال: C:\Program Files\Borland\Delphi 7\bin، أو C:\Program Files\Embarcadero\RAD Studio\7.0\Bin) ;
  • في مجلد Bin الذي تم العثور عليه، نبحث بالفعل عن الملف com.dclsockets [هنا الأرقام].bpl، انقر فوق موافق؛
  • نحن سعداء لأنه لدينا الآن مكونان رائعان TServerSocket وTClientSocket في علامة تبويب الإنترنت بلوحة المكونات.

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

الخصائص الأساسية:

  • نشيط- حقل منطقي، عند ضبطه على true - يبدأ الخادم، يمكنك استخدامه إما عن طريق تعيين قيم محددة أو عن طريق استدعاء الوظائف ServerSocket1.Open (... Active:=true;) أو ServerSocket1.Close (.. . نشط:=خطأ).
  • ميناء– المنفذ الذي سيستمع عليه الخادم (استقبال العملاء)، أي قيمة ضمن النطاق لا تشغلها خوادم أخرى في النظام عدد صحيح.

الاحداث الرئيسية:

  • OnListen- يتم استدعاؤه عندما يكون الخادم مضبوطًا على وضع الاستماع، ويمكن استخدامه عندما نحتاج إلى تحديد وقت البداية الحقيقية للخادم.
  • قراءة OnClient- يتم الاتصال به عند استلام البيانات من العميل.
  • خطأ في OnClientError
  • OnClientConnect– يتم الاتصال به عند انضمام عميل جديد إلى الخادم.
  • OnClientDisconnect- عكس الحدث إلى الحدث، OnClientConnect

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

الخصائص والوظائف للقراءة فقط:

  • - إرجاع عدد الاتصالات النشطة.
  • ServerSocket1.Socket.Connections– مصفوفة من الكائنات من نوع TCustomWinSocket، مصفوفة من كافة الكائنات المرتبطة بالعملاء، يبدأ عد الفهرس من 0، طول المصفوفة هو ServerSocket1.Socket.ActiveConnections.
  • الوظائف والخصائص التي تنطبق على عناصر صفيف ServerSocket1.Socket.Connections وسمة المقبس التي تم تمريرها إلى وظيفة حدث الخادم:
  • المقبس.المضيف المحلي
  • المقبس.العنوان المحلي– إرجاع IP الخادم.
  • المقبس.RemoteHost
  • المقبس.RemoteAddress- إرجاع IP العميل.
  • المقبس.تلقي النص– إرجاع رسالة نصية مستلمة من العميل، وبعد ذلك يقوم بمسح المخزن المؤقت، ويمكن استخدامها مرة واحدة فقط، لكل استقبال واحد.
  • المقبس.إرسال نص (نص)– إرسال رسالة نصية من نوع Text إلى العميل خيط.

بالنسبة لمكون TClientSocket، كل شيء هو نفسه عمليًا، فقط في الاتجاه المعاكس + الفرق المرئي الرئيسي بين الخادم والعميل هو أنه يمكن تشغيل الخادم في النظام بقيمة منفذ 1 × 1، وعدد العملاء محدود فقط بواسطة ذاكرة الوصول العشوائي (RAM) .

الخصائص الأساسية:

  • نشيط- حقل منطقي، عند ضبطه على "صحيح" - يحاول العميل الاتصال بالخادم، ويمكن استخدامه إما عن طريق تعيين قيم محددة أو عن طريق استدعاء الوظائف ClientSocket1.Open (... Active:=true;) أو ClientSocket1 .إغلاق (... نشط:=خطأ) .
  • ميناء- المنفذ الذي يمكن للعميل من خلاله الاتصال بالخادم، أي قيمة ضمن النطاق عدد صحيح.
  • عنوان– عنوان IPv4 لنوع الخادم خيطوفقًا للنمط 255.255.255.255 الذي سيتصل به العميل.

الاحداث الرئيسية:

  • على القراءة- يتم الاتصال به عند استلام البيانات من الشمال.
  • خطأ– يتم استدعاؤه عند حدوث خطأ في نقل البيانات.
  • عند الاتصال– يتم الاتصال به عند انضمام العميل إلى الخادم.
  • عند قطع الاتصال- عكس الحدث إلى الحدث، عند الاتصال، يتم استدعاؤه عندما ينقطع اتصال العميل بالخادم.

الخصائص والوظائف للقراءة فقط:

  • ClientSocket1.Socket.SendText() خيط
  • المقبس.المضيف المحلي– إرجاع اسم العميل عبر الإنترنت.
  • المقبس.العنوان المحلي- إرجاع IP العميل.
  • المقبس.RemoteHost– إرجاع اسم الخادم على الشبكة.
  • المقبس.RemoteAddress– إرجاع IP الخادم.
  • المقبس.تلقي النص– إرجاع رسالة نصية مستلمة من الخادم، وبعد ذلك يقوم بمسح المخزن المؤقت، ويمكن استخدامه مرة واحدة فقط في كل مرة.
  • المقبس.إرسال نص (نص)– إرسال رسالة نصية من نوع Text إلى الخادم خيط.

المعلومات المقدمة كافية تمامًا لتنفيذ دردشة خادم صغيرة تُرضي المواصفات الفنية: internet_sockets.doc (Word Doc 97-2003، 26.5 كيلو بايت).

تم نشر هذه المقالة يوم الأحد 10 أكتوبر 2010 الساعة 1:24 صباحًا في القسم. يمكنك الاشتراك في التحديثات على التعليقات على المقال -. أنت تستطيع


مقدمة


هذه المقالة مخصصة لإنشاء تطبيقات بنية العميل/الخادم في بورلاند دلفي بناءً على المقابس ("المقابس" - أعشاش). على عكس المقالة السابقة حول موضوع المقابس، سننظر هنا في إنشاء تطبيقات الخادم.

تجدر الإشارة على الفور إلى أنه من أجل التعايش بين تطبيقات العميل والخادم المنفصلة، ​​ليس من الضروري أن يكون لديك عدة أجهزة كمبيوتر. يكفي أن يكون لديك واحد فقط يمكنك من خلاله تشغيل كل من الخادم والعميل في نفس الوقت. في هذه الحالة، تحتاج إلى استخدام اسم المضيف كاسم الكمبيوتر الذي تريد الاتصال به مضيف محليأو عنوان IP - 127.0.0.1 .

لذلك، دعونا نبدأ مع النظرية. إذا كنت ممارسًا مقتنعًا (ولا يمكنك رؤية أي خوارزميات بعينيك)، فعليك تخطي هذا القسم.

خوارزمية تشغيل خادم المقبس


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

فيما يلي مثال تخطيطي لكيفية عمل خادم المقبس في تطبيقات دلفي:

دعونا نلقي نظرة على الرسم البياني بمزيد من التفاصيل:

  • تعريف خصائص المنفذ و ServerType - لكي يتمكن العملاء من الاتصال بالخادم بشكل طبيعي، من الضروري أن يتطابق المنفذ الذي يستخدمه الخادم تمامًا مع المنفذ الذي يستخدمه العميل (والعكس صحيح). تحدد الخاصية ServerType نوع الاتصال (انظر أدناه لمزيد من التفاصيل)؛
  • فتح المقبس - فتح المقبس والمنفذ المحدد . هذا هو المكان الذي نبدأ فيه تلقائيًا في انتظار اتصال العملاء ( يستمع);
  • ربط العميل وتبادل البيانات معه - هنا يقوم العميل بالاتصال وتبادل البيانات معه. يمكنك معرفة المزيد حول هذه المرحلة أدناه في هذه المقالة وفي المقالة حول المقابس (جزء العميل)؛
  • تعطيل العميل - هنا يتم قطع اتصال العميل ويتم إغلاق اتصال المقبس الخاص به بالخادم؛
  • إغلاق الخادم والمقبس - بناء على أمر المسؤول، يتم إيقاف تشغيل الخادم، وإغلاق جميع القنوات المفتوحة وإيقاف انتظار اتصالات العميل.

تجدر الإشارة إلى أن النقاط 3-4 تتكرر عدة مرات، أي. يتم تنفيذ هذه الخطوات لكل اتصال عميل جديد.

ملحوظة : هناك القليل جدًا من الوثائق حول المقابس في دلفي في الوقت الحالي، لذا إذا كنت تريد دراسة هذا الموضوع بتعمق قدر الإمكان، أنصحك بالاطلاع على الأدبيات والوثائق الإلكترونية الخاصة بأنظمة Unix/Linux - هناك جداًتم وصف نظرية العمل مع المقابس بشكل جيد. بالإضافة إلى ذلك، هناك العديد من الأمثلة على تطبيقات مأخذ التوصيل لأنظمة التشغيل هذه (على الرغم من أن معظمها في C/C++ وPerl).

وصف موجز لمكون TServerSocket


وهنا سوف نتعرف رئيسيخصائص وأساليب وأحداث المكون TServerSocket.

ملكيات

قابس كهرباء - فئة TServerWinSocket، والتي من خلالها يمكنك الوصول إلى قنوات المقابس المفتوحة. بعد ذلك، سننظر في هذه الخاصية بمزيد من التفصيل، لأن إنها في الواقع واحدة من أهمها. يكتب: TServerWinSocket ;
نوع الخادم - نوع الخادم. يمكن أن تأخذ إحدى القيمتين: stNonBlocking- العمل المتزامن مع مآخذ العميل. باستخدام هذا النوع من الخوادم، يمكنك العمل مع العملاء من خلال الأحداث قراءة OnClientو OnClientWrite. stThreadBlocking- نوع غير متزامن. يتم إنشاء عملية منفصلة (خيط) لكل قناة مأخذ توصيل للعميل. يكتب: TServerType ;
ThreadCacheSize - عدد عمليات العميل (الخيط) التي سيتم تخزينها مؤقتًا بواسطة الخادم. تحتاج هنا إلى تحديد القيمة المتوسطة اعتمادًا على التحميل على الخادم الخاص بك. يحدث التخزين المؤقت من أجل عدم إنشاء عملية منفصلة في كل مرة وعدم قتل مأخذ توصيل مغلق، ولكن تركها لاستخدامها لاحقًا. يكتب: عدد صحيح ;
نشيط - مؤشر لمعرفة ما إذا كان الخادم نشطًا في لحظة معينة أم لا. وهذا هو، في الواقع، القيمة حقيقييشير إلى أن الخادم قيد التشغيل وجاهز لاستقبال العملاء، و خطأ شنيع- تم إيقاف الخادم. لبدء الخادم، تحتاج ببساطة إلى تعيين هذه الخاصية حقيقي. يكتب: منطقية ;
ميناء - رقم المنفذ لإنشاء اتصالات مع العملاء. يجب أن تكون منافذ الخادم والعميل هي نفسها. يوصى بالقيم من 1025 إلى 65535، لأن من 1 إلى 1024 - يمكن أن يشغلها النظام. يكتب: عدد صحيح ;
خدمة - سلسلة تحدد الخدمة ( ftp, http, البوب، وما إلى ذلك) الذي سيتم استخدام منفذه. هذا نوع من دليل أرقام المنافذ المتوافقة مع البروتوكولات القياسية المختلفة. يكتب: خيط ;

يفتح - يبدأ الخادم. في الأساس، هذا الأمر مطابق لتعيين قيمة حقيقيملكية نشيط;
يغلق - توقف الخادم. في الأساس، هذا الأمر مطابق لتعيين قيمة خطأ شنيعملكية نشيط.

OnClientConnect - يحدث عندما يقوم العميل بإنشاء اتصال مأخذ توصيل وينتظر استجابة من الخادم ( عند قبول);
OnClientDisconnect - يحدث عندما ينقطع اتصال العميل بقناة المقبس؛
خطأ في OnClientError - يحدث عندما تفشل العملية الحالية، أي. حدث خطأ؛
قراءة OnClient - يحدث عندما يرسل العميل بعض البيانات إلى الخادم. يمكن الوصول إلى هذه البيانات من خلال معلمة تم تمريرها المقبس: TCustomWinSocket;
OnClientWrite - يحدث عندما يتمكن الخادم من إرسال البيانات إلى العميل عبر مأخذ توصيل؛
OnGetSocket - في معالج هذا الحدث يمكنك تحرير المعلمة ClientSocket;
OnGetThread - في معالج هذا الحدث، يمكنك تحديد عملية فريدة (خيط) لكل قناة عميل فردية عن طريق تعيين المعلمة موضوع المقبسالمهمة الفرعية المطلوبة TServerClientThread؛
OnThreadStart , OnThreadEnd - يحدث عند بدء أو إيقاف مهمة فرعية (عملية، مؤشر ترابط)، على التوالي؛
عند قبول - يحدث عندما يقبل الخادم العميل أو يرفض الاتصال به؛
OnListen - يحدث عندما ينتقل الخادم إلى وضع الانتظار حتى يتمكن العملاء من الاتصال.


TServerSocket.Socket(TSServerWinSocket)


فكيف يمكن للخادم إرسال البيانات إلى العميل؟ ماذا عن قبول البيانات؟ بشكل رئيسي إذا كنت تعمل من خلال الأحداث قراءة OnClientو OnClientWrite، ثم يمكنك التواصل مع العميل من خلال معلمة ClientSocket (TCustomWinSocket). يمكنك أن تقرأ عن العمل مع هذه الفئة في المقالة حول مآخذ توصيل العميل، لأن إرسال/إرسال البيانات من خلال هذه الفئة مشابه - الطرق (إرسال/تلقي) (نص، مخزن مؤقت، دفق). وينطبق الشيء نفسه عند العمل مع TServerSocket.Socket. ومع ذلك، لأن نحن هنا نفكر في الخادم، ويجب أن نسلط الضوء على بعض الخصائص والأساليب المفيدة:

  • اتصالات نشطة (عدد صحيح) - عدد العملاء المتصلين؛
  • المواضيع النشطة (عدد صحيح) - عدد العمليات الجارية؛
  • روابط (مجموعة مصفوفة) - مصفوفة تتكون من فئات TClientWinSocket منفصلة لكل عميل متصل. على سبيل المثال هذا الأمر:
    ServerSocket1.Socket.Connections.SendText("مرحبا!");
    يرسل رسالة "مرحبًا!" إلى العميل المتصل الأول. أوامر للعمل مع عناصر هذه المصفوفة - أيضًا (إرسال/تلقي)(Text,Buffer, Stream);
  • IdleThreads (عدد صحيح) - عدد العمليات المجانية. يتم تخزين هذه العمليات مؤقتًا بواسطة الخادم (انظر ThreadCacheSize);
  • عنوان محلي, مضيف محلي, ميناء محلي- على التوالى - عنوان IP المحلي، اسم المضيف، المنفذ؛
  • عنوان بعيد, المضيف البعيد, RemotePort- على التوالي - عنوان IP البعيد، واسم المضيف، والمنفذ؛
  • طُرق قفلو الغاء القفل- على التوالي، حظر وإلغاء حظر المقبس.

الممارسة والأمثلة


الآن دعونا نلقي نظرة على ما سبق مثال محدد. يمكنك تنزيل المصادر الجاهزة بالنقر فوق.

لذلك، دعونا نلقي نظرة على مثال جيد جدًا للعمل مع TServerSocket (هذا المثال هو أكثر المساعدات المرئية لدراسة هذا المكون). توضح المصادر أدناه تسجيل جميع أحداث الخادم المهمة، بالإضافة إلى القدرة على الاستلام والإرسال رسائل نصية:

مثال 1.التسجيل والدراسة عملية الخادم، إرسال/استقبال الرسائل عبر المقابس

(...هنا يظهر رأس الملف وتعريف النموذج TForm1 ومثيله Form1)
(انظر المصدر كاملا)
الإجراء TForm1.Button1Click(Sender: TObject); يبدأ (تحديد المنفذ وبدء تشغيل الخادم) ServerSocket1.Port:= 1025; (تقوم طريقة الإدراج بإدراج سلسلة في الصفيف في الموضع المحدد) Memo2.Lines.Insert(0"بدء تشغيل الخادم"); ServerSocket1.Open; نهاية؛ الإجراء TForm1.Button2Click(Sender: TObject); يبدأ (أوقف الخادم) ServerSocket1.Active:= خطأ؛ Memo2.Lines.Insert(0,"توقف الخادم"); نهاية؛ الإجراء TForm1.ServerSocket1Listen(Sender: TObject; المقبس: TCustomWinSocket); يبدأ (هنا "يستمع" الخادم إلى المقبس للعملاء) Memo2.Lines.Insert(0،"الاستماع على المنفذ "+IntToStr(ServerSocket1.Port)); نهاية؛ الإجراء TForm1.ServerSocket1Accept(Sender: TObject; المقبس: TCustomWinSocket); يبدأ (هنا يقبل الخادم العميل) Memo2.Lines.Insert(0,"تم قبول اتصال العميل"); نهاية؛ الإجراء TForm1.ServerSocket1ClientConnect(Sender: TObject; المقبس: TCustomWinSocket); يبدأ (هنا يتصل العميل) Memo2.Lines.Insert(0,"العميل متصل"); نهاية؛ الإجراء TForm1.ServerSocket1ClientDisconnect(Sender: TObject; المقبس: TCustomWinSocket); يبدأ (هنا يتم قطع اتصال العميل) Memo2.Lines.Insert(0,"العميل غير متصل"); نهاية؛ الإجراء TForm1.ServerSocket1ClientError(Sender: TObject; المقبس: TCustomWinSocket; ErrorEvent: TERrorEvent; var ErrorCode: Integer); يبدأ (حدث خطأ - اعرض الكود الخاص به) Memo2.Lines.Insert(0,"Client error.Code = "+IntToStr(ErrorCode)); نهاية؛ الإجراء TForm1.ServerSocket1ClientRead(Sender: TObject; المقبس: TCustomWinSocket); يبدأ (تم استلام رسالة من العميل - اعرضها في المذكرة 1) Memo2.Lines.Insert(0"الرسالة المستلمة من العميل"); Memo1.Lines.Insert(0,"> "+Socket.ReceiveText); نهاية؛ الإجراء TForm1.ServerSocket1ClientWrite(Sender: TObject; المقبس: TCustomWinSocket); يبدأ (الآن يمكنك إرسال البيانات إلى المقبس) Memo2.Lines.Insert(0,"الآن يمكنك الكتابة إلى المقبس"); نهاية؛ الإجراء TForm1.ServerSocket1GetSocket(Sender: TObject; المقبس: Integer; var ClientSocket: TServerClientWinSocket); ابدأ Memo2.Lines.Insert(0,"احصل على المقبس"); نهاية؛ الإجراء TForm1.ServerSocket1GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket; var JackThread: TServerClientThread); ابدأ Memo2.Lines.Insert(0,"Get Thread"); نهاية؛ الإجراء TForm1.ServerSocket1ThreadEnd(Sender: TObject; Thread: TServerClientThread); begin Memo2.Lines.Insert(0,"نهاية الموضوع"); نهاية؛ الإجراء TForm1.ServerSocket1ThreadStart(Sender: TObject; Thread: TServerClientThread); begin Memo2.Lines.Insert(0,"Thread start"); نهاية؛ الإجراء TForm1.Button3Click(Sender: TObject); فار ط: عدد صحيح؛ يبدأ (أرسل رسالة إلى جميع العملاء من Edit1) بالنسبة إلى i:= 0 إلى ServerSocket1.Socket.ActiveConnections-1، ابدأ ServerSocket1.Socket.Connections[i].SendText(Edit1.Text); نهاية؛ مذكرة 1. خطوط. إدراج (0، "

تقنيات العمل مع TServerSocket (وببساطة مع المقابس)


تخزين بيانات فريدة لكل عميل.


بالتأكيد، إذا كان خادمك سيخدم العديد من العملاء، فستحتاج إلى تخزين بعض المعلومات لكل عميل (الاسم، وما إلى ذلك)، وربط هذه المعلومات بمقبس هذا العميل. في بعض الحالات، القيام بكل هذا يدويًا (الربط بمقبض مأخذ التوصيل، أو مصفوفات العميل، وما إلى ذلك) ليس أمرًا مريحًا للغاية. لذلك، لكل مقبس هناك خاصية خاصة - بيانات. في الواقع، البيانات هي مجرد مؤشر. لذلك، عند كتابة بيانات العميل إلى هذه الخاصية، كن حذرًا واتبع قواعد العمل مع المؤشرات (تخصيص الذاكرة، تعريف النوع، وما إلى ذلك)!

إرسال الملفات عبر المقبس.


سننظر هنا في إرسال الملفات عبر مأخذ توصيل (بناءً على طلب JINX) :-). إذًا كيف يمكنك إرسال ملف عبر مأخذ توصيل؟ بسيط جدا! كل ما عليك فعله هو فتح هذا الملف كملف دفق (TFileStream) وإرساله عبر مأخذ توصيل (SendStream)! دعونا ننظر إلى هذا مع مثال:

وتجدر الإشارة إلى أن الطريقة إرسال تياريستخدم ليس فقط من قبل الخادم، ولكن أيضًا من قبل العميل ( ClientSocket1.Socket.SendStream(srcfile))

لماذا يمكن دمج عدة كتل في كتلة واحدة أثناء الإرسال؟


وهذا أيضًا بناءً على طلب JINX :-). شكرا جزيلا له على هذا! لذا، أولاً، تجدر الإشارة إلى أن البيانات المرسلة عبر المقبس لا يمكن دمجها في كتلة واحدة فحسب، بل يمكن أيضًا فصلها عبر عدة كتل. الحقيقة هي أن المقبس عبارة عن دفق عادي، ولكن على عكس، على سبيل المثال، دفق الملفات (TFileStream)، فإنه ينقل البيانات بشكل أبطأ (كما تفهم - الشبكة، وحركة المرور المحدودة، وما إلى ذلك). ولهذا أمران:
ServerSocket1.Socket.Connections.SendText("Hello, ");
ServerSocket1.Socket.Connections.SendText("world!");
متطابق تمامًا مع أمر واحد:
ServerSocket1.Socket.Connections.SendText("مرحبا بالعالم!");

ولهذا السبب، إذا قمت بإرسال ملف بحجم 100 كيلو بايت عبر مأخذ توصيل، فإن الشخص الذي أرسلت إليه هذه الكتلة سيتلقى عدة كتل بأحجام تعتمد على حركة المرور وازدحام الخط. علاوة على ذلك، فإن الأحجام لن تكون بالضرورة هي نفسها. ويترتب على ذلك من أجل قبول ملف أو أي بيانات أخرى حجم كبيريجب عليك قبول كتل من البيانات ثم دمجها في وحدة واحدة (وحفظها في ملف، على سبيل المثال). الحل الأمثل لهذه المشكلة هو نفس دفق الملف - TFileStream (أو دفق في الذاكرة - TMemoryStream). يمكنك تلقي أجزاء من البيانات من مأخذ التوصيل من خلال حدث OnRead (OnClientRead) باستخدام الطريقة العامة تلقيBuf. يمكنك تحديد حجم الكتلة الناتجة باستخدام الطريقة طول التلقي. يمكنك أيضًا استخدام دفق مأخذ التوصيل (راجع المقالة حول TClientSocket). وهنا مثال صغير (تقريبي):

كيفية مراقبة المقبس


هذه القضية معقدة وتتطلب دراسة طويلة. في الوقت الحالي، سأشير فقط إلى أنه يمكنك دائمًا مراقبة المقبس الذي أنشأه برنامجك :-). المقابس (مثل معظم الكائنات في Windows) لها مقبض خاص بها، مكتوب في خاصية Handle. لذا، بمجرد التعرف على هذا الواصف، ستتمكن من إدارة أي مقبس بحرية (حتى تلك التي أنشأها برنامج شخص آخر)! ومع ذلك، على الأرجح، لمراقبة مأخذ توصيل شخص آخر، سيتعين عليك استخدام وظائف WinAPI مقبس حصريا.


توضح هذه المقالة التقنيات الأساسية للعمل مع مكون TServerSocket في دلفي والعديد من التقنيات العامة لتبادل البيانات عبر المقابس. إذا كان لديك أسئلة، أرسلها لي عبر البريد الإلكتروني: [البريد الإلكتروني محمي]والأفضل من ذلك - الكتابة في مؤتمر هذا الموقع (أسئلة دلفي العامة) حتى يتمكن المستخدمون الآخرون من رؤية سؤالك ومحاولة الإجابة عليه!

كاريخ نيكولاي ( نيترو). منطقة موسكو، جوكوفسكي

هذه المقالة مخصصة لإنشاء تطبيقات بنية العميل/الخادم في بورلاند دلفي بناءً على المقابس ("المقابس"). على عكس المقالة السابقة حول موضوع المقابس، سننظر هنا في إنشاء تطبيقات الخادم.
تجدر الإشارة على الفور إلى أنه من أجل التعايش بين تطبيقات العميل والخادم المنفصلة، ​​ليس من الضروري أن يكون لديك عدة أجهزة كمبيوتر. يكفي أن يكون لديك واحد فقط يمكنك من خلاله تشغيل كل من الخادم والعميل في نفس الوقت. في هذه الحالة، تحتاج إلى استخدام اسم المضيف localhost أو عنوان IP - 127.0.0.1 كاسم الكمبيوتر الذي تريد الاتصال به.
لذلك، دعونا نبدأ مع النظرية. إذا كنت ممارسًا مقتنعًا (ولا يمكنك رؤية أي خوارزميات بعينيك)، فعليك تخطي هذا القسم.
خوارزمية تشغيل خادم المقبس
ماذا يسمح لك خادم المقبس بفعله؟.. على أي مبدأ يعمل؟.. خادم يعتمد على بروتوكول المقبس يسمح لك بخدمة العديد من العملاء في وقت واحد. علاوة على ذلك، يمكنك تحديد الحد الأقصى لعددهم بنفسك (أو إزالة هذا الحد تمامًا، كما هو الحال افتراضيًا). لكل عميل متصل، يفتح الخادم مقبسًا منفصلاً يمكنك من خلاله تبادل البيانات مع العميل. الحل الرائع الآخر هو إنشاء عملية منفصلة (خيط) لكل اتصال.
فيما يلي مثال تخطيطي لكيفية عمل خادم المقبس في تطبيقات دلفي:

دعونا نلقي نظرة على المخطط بمزيد من التفاصيل: · تعريف المنفذ ونوع الخادم - لكي يتمكن العملاء من الاتصال بالخادم بشكل طبيعي، من الضروري أن يتطابق المنفذ الذي يستخدمه الخادم تمامًا مع المنفذ الذي يستخدمه العميل (و والعكس صحيح). تحدد الخاصية ServerType نوع الاتصال (انظر أدناه لمزيد من التفاصيل)؛ · فتح المقبس - فتح المقبس والمنفذ المحدد. هنا البداية التلقائية لانتظار اتصال العملاء (الاستماع)؛ · الاتصال بالعميل وتبادل البيانات معه – هنا يتصل العميل ويتبادل البيانات معه. يمكنك معرفة المزيد حول هذه المرحلة أدناه في هذه المقالة وفي المقالة حول المقابس (جزء العميل)؛ · قطع اتصال العميل - هنا يتم قطع اتصال العميل وإغلاق اتصال المقبس الخاص به بالخادم؛ · إغلاق الخادم والمقبس - بناءً على أمر المسؤول، يتم إيقاف تشغيل الخادم، وإغلاق جميع قنوات المقبس المفتوحة وإيقاف انتظار اتصالات العميل.
تجدر الإشارة إلى أن النقاط 3-4 تتكرر عدة مرات، أي. يتم تنفيذ هذه الخطوات لكل اتصال عميل جديد.
ملاحظة: هناك القليل جدًا من الوثائق حول المقابس في دلفي في الوقت الحالي، لذا إذا كنت تريد دراسة هذا الموضوع بتعمق قدر الإمكان، أنصحك بالاطلاع على الأدبيات والوثائق الإلكترونية الخاصة بأنظمة Unix/Linux - نظرية العمل مع تم وصف المآخذ بشكل جيد للغاية هناك. بالإضافة إلى ذلك، هناك العديد من الأمثلة على تطبيقات مأخذ التوصيل لأنظمة التشغيل هذه (على الرغم من أن معظمها في C/C++ وPerl).
وصف موجز لمكون TServerSocket
هنا سوف نتعرف على الخصائص والأساليب والأحداث الرئيسية للمكون
ملكيات
المقبس هو فئة TServerWinSocket التي يمكنك من خلالها الوصول إلى قنوات المقابس المفتوحة. بعد ذلك، سننظر في هذه الخاصية بمزيد من التفصيل، لأن إنها في الواقع واحدة من أهمها. النوع: TServerWinSocket;
نوع الخادم - نوع الخادم. يمكن أن يأخذ إحدى القيمتين: stNonBlocking - العمل المتزامن مع مآخذ توصيل العميل. باستخدام هذا النوع من الخوادم، يمكنك العمل مع العملاء من خلال الأحداث OnClientRead وOnClientWrite. stThreadBlocking هو نوع غير متزامن. يتم إنشاء عملية منفصلة (خيط) لكل قناة مأخذ توصيل للعميل. النوع: TServerType؛
ThreadCacheSize - عدد عمليات العميل (Thread) التي سيتم تخزينها مؤقتًا بواسطة الخادم. تحتاج هنا إلى تحديد القيمة المتوسطة اعتمادًا على التحميل على الخادم الخاص بك. يحدث التخزين المؤقت من أجل عدم إنشاء عملية منفصلة في كل مرة وعدم قتل مأخذ توصيل مغلق، ولكن تركها لاستخدامها لاحقًا. النوع: عدد صحيح؛
نشط - مؤشر على ما إذا كان الخادم نشطًا حاليًا أم لا. أي أن القيمة True تشير في الواقع إلى أن الخادم قيد التشغيل وجاهز لاستقبال العملاء، وتشير القيمة False إلى أن الخادم متوقف عن التشغيل. لبدء الخادم، ما عليك سوى ضبط هذه الخاصية على True. النوع: منطقي؛
المنفذ - رقم المنفذ لإنشاء اتصالات مع العملاء. يجب أن تكون منافذ الخادم والعميل هي نفسها. يوصى بالقيم من 1025 إلى 65535، لأن من 1 إلى 1024 - يمكن أن يشغلها النظام. النوع: عدد صحيح؛
الخدمة - سلسلة تحدد الخدمة (ftp، http، pop، وما إلى ذلك) التي سيتم استخدام المنفذ الخاص بها. هذا نوع من دليل أرقام المنافذ المتوافقة مع البروتوكولات القياسية المختلفة. النوع: سلسلة؛
طُرق
فتح - يبدأ تشغيل الخادم. بشكل أساسي، هذا الأمر مماثل لتعيين الخاصية النشطة إلى True؛
إغلاق - يوقف الخادم. بشكل أساسي، هذا الأمر مماثل لتعيين الخاصية النشطة إلى False.
الأحداث
OnClientConnect - يحدث عندما يقوم العميل بإنشاء اتصال مأخذ توصيل وينتظر استجابة من الخادم (OnAccept)؛
OnClientDisconnect - يحدث عندما ينقطع اتصال العميل بقناة مأخذ التوصيل؛
OnClientError - يحدث عندما تفشل العملية الحالية، أي. حدث خطأ؛
OnClientRead - يحدث عندما يقوم العميل بتمرير بعض البيانات إلى الخادم. يمكن الوصول إلى هذه البيانات من خلال معلمة المقبس المتوفرة: TCustomWinSocket;
OnClientWrite - يحدث عندما يتمكن الخادم من إرسال البيانات إلى العميل عبر المقبس؛
OnGetSocket - في معالج هذا الحدث، يمكنك تحرير معلمة ClientSocket؛
OnGetThread - في معالج هذا الحدث، يمكنك تحديد عملية فريدة (Thread) لكل قناة عميل فردية عن طريق تعيين معلمة ConnectorThread للمهمة الفرعية TServerClientThread المطلوبة؛
OnThreadStart، OnThreadEnd - يحدث عند بدء مهمة فرعية (عملية، مؤشر ترابط) أو إيقافها، على التوالي؛
OnAccept - يحدث عندما يقبل الخادم العميل أو يرفض الاتصال به؛
OnListen - يحدث عندما ينتقل الخادم إلى وضع الانتظار حتى يتمكن العملاء من الاتصال.
TServerSocket.Socket(TSServerWinSocket)
فكيف يمكن للخادم إرسال البيانات إلى العميل؟ ماذا عن قبول البيانات؟ بشكل أساسي، إذا كنت تعمل من خلال الأحداث OnClientRead وOnClientWrite، فيمكنك التواصل مع العميل من خلال معلمة ClientSocket (TCustomWinSocket). يمكنك أن تقرأ عن العمل مع هذه الفئة في المقالة حول مآخذ توصيل العميل، لأن إرسال/إرسال البيانات من خلال هذه الفئة مشابه - الطرق (إرسال/تلقي) (نص، مخزن مؤقت، دفق). وينطبق الشيء نفسه عند العمل مع TServerSocket.Socket. ومع ذلك، لأن نحن هنا نفكر في الخادم، ويجب أن نسلط الضوء على بعض الخصائص والأساليب المفيدة: · ActiveConnections (Integer) - عدد العملاء المتصلين؛ · ActiveThreads (عدد صحيح) - عدد العمليات الجارية؛ ·الاتصالات (المصفوفة) - مصفوفة تتكون من فئات TClientWinSocket منفصلة لكل عميل متصل. على سبيل المثال، هذا الأمر: · ServerSocket1.Socket.Connections.SendText("Hello!"); · يرسل رسالة "Hello!" إلى العميل الأول المتصل. أوامر للعمل مع عناصر هذه المصفوفة - أيضًا (إرسال/تلقي)(Text,Buffer, Stream); ·IdleThreads (عدد صحيح) - عدد العمليات المجانية. يتم تخزين هذه العمليات مؤقتًا بواسطة الخادم (راجع ThreadCacheSize)؛ · LocalAddress و LocalHost و LocalPort - على التوالي - عنوان IP المحلي واسم المضيف والمنفذ؛ ·RemoteAddress وRemoteHost وRemotePort - على التوالي - عنوان IP البعيد واسم المضيف والمنفذ؛ · طرق القفل والفتح - على التوالي، حظر وإلغاء قفل المقبس.
الممارسة والأمثلة
الآن دعونا نلقي نظرة على ما ورد أعلاه باستخدام مثال محدد. يمكنك تحميل المصادر الجاهزة بالضغط هنا.
لذلك، دعونا نلقي نظرة على مثال جيد جدًا للعمل مع TServerSocket (هذا المثال هو أكثر المساعدات المرئية لدراسة هذا المكون). توضح المصادر أدناه تسجيل جميع أحداث الخادم المهمة، بالإضافة إلى القدرة على استقبال وإرسال الرسائل النصية:
مثال 1. تسجيل ودراسة تشغيل الخادم، وإرسال/استقبال الرسائل عبر المقابس.

(...هنا يظهر رأس الملف وتعريف النموذج TForm1 ومثيله Form1)

(انظر المصدر الكامل هنا)

الإجراء TForm1.Button1Click (المرسل: TObject) ؛

يبدأ

(تحديد المنفذ وبدء تشغيل الخادم)

ServerSocket1.Port := 1025 ;

(تقوم طريقة الإدراج بإدراج سلسلة في الصفيف في الموضع المحدد)

Memo2.Lines .Insert (0 , "بدء تشغيل الخادم" ) ;

ServerSocket1.Open؛

نهاية ؛

الإجراء TForm1.Button2Click (المرسل: TObject) ؛

يبدأ

(أوقف الخادم)

ServerSocket1.Active := خطأ ;

Memo2.Lines .Insert (0 , "توقف الخادم" ) ;

نهاية ؛

الإجراء TForm1.ServerSocket1Listen (المرسل: TObject ;

المقبس: TCustomWinSocket)؛

يبدأ

(هنا "يستمع" الخادم إلى المقبس للعملاء)

Memo2.Lines .Insert (0، "الاستماع على المنفذ" +IntToStr (ServerSocket1.Port ) ) ؛

نهاية ؛

الإجراء TForm1.ServerSocket1Accept (المرسل: TObject ;

المقبس: TCustomWinSocket)؛

يبدأ

(هنا يقبل الخادم العميل)

Memo2.Lines .Insert (0، "تم قبول اتصال العميل")؛

نهاية ؛

الإجراء TForm1.ServerSocket1ClientConnect (المرسل: TObject ;

المقبس: TCustomWinSocket)؛

يبدأ

(هنا يتصل العميل)

Memo2.Lines .Insert (0، "العميل متصل")؛

نهاية ؛

الإجراء TForm1.ServerSocket1ClientDisconnect (المرسل: TObject ;

المقبس: TCustomWinSocket)؛

يبدأ

(هنا يتم قطع اتصال العميل)

Memo2.Lines.Insert(0,"العميل غير متصل");

نهاية ؛

الإجراء TForm1.ServerSocket1ClientError (المرسل: TObject ;

المقبس: TCustomWinSocket؛ ErrorEvent: TERrorEvent;

فار ErrorCode: عدد صحيح)؛

يبدأ

(حدث خطأ - اعرض الكود الخاص به)

Memo2.Lines.Insert (0،"خطأ العميل. Code = " +IntToStr (ErrorCode) ) ;

نهاية ؛

الإجراء TForm1.ServerSocket1ClientRead (المرسل: TObject ;

المقبس: TCustomWinSocket)؛

يبدأ

(تم استلام رسالة من العميل - اعرضها في المذكرة 1)

مذكرة 2. خطوط. إدراج (0، "تم استلام الرسالة من العميل") ;

Memo1.Lines.Insert(0,">" +Socket.ReceiveText);

نهاية ؛

الإجراء TForm1.ServerSocket1ClientWrite (المرسل: TObject ;

المقبس: TCustomWinSocket)؛

يبدأ

(الآن يمكنك إرسال البيانات إلى المقبس)

Memo2.Lines .Insert (0 , "الآن يمكن الكتابة إلى المقبس" ) ;

نهاية ؛

الإجراء TForm1.ServerSocket1GetSocket (المرسل: TObject ; المقبس: Integer ;

فار ClientSocket: TServerClientWinSocket);

يبدأ

Memo2.Lines .Insert (0 , "الحصول على المقبس" ) ;

نهاية ؛

الإجراء TForm1.ServerSocket1GetThread (المرسل: TObject ;

ClientSocket: TServerClientWinSocket;

var SwitchThread: TServerClientThread) ;

يبدأ

Memo2.Lines.Insert(0,"احصل على الموضوع");

نهاية ؛

الإجراء TForm1.ServerSocket1ThreadEnd (المرسل: TObject ;

يبدأ

Memo2.Lines .Insert (0، "نهاية الموضوع")؛

نهاية ؛

الإجراء TForm1.ServerSocket1ThreadStart (المرسل: TObject ;

الموضوع: TServerClientThread) ؛

يبدأ

Memo2.Lines .Insert (0 , "Thread start" ) ;

نهاية ؛

الإجراء TForm1.Button3Click (المرسل: TObject) ؛

فار ط: عدد صحيح؛

يبدأ

(أرسل رسالة إلى جميع العملاء من Edit1)

بالنسبة إلى i:= 0 إلى ServerSocket1.Socket .ActiveConnections -1 تبدأ

ServerSocket1.Socket.Connections[i].SendText(Edit1.Text);

نهاية ؛

مذكرة 1. خطوط. إدراج (0، "< " +Edit1.Text ) ;

نهاية ؛

بعد ذلك، لن نفكر في الأمثلة، ولكن طرق العمل مع TServerSocket.
تقنيات العمل مع TServerSocket (وببساطة مع المقابس)
تخزين بيانات فريدة لكل عميل.
بالتأكيد، إذا كان خادمك سيخدم العديد من العملاء، فستحتاج إلى تخزين بعض المعلومات لكل عميل (الاسم، وما إلى ذلك)، وربط هذه المعلومات بمقبس هذا العميل. في بعض الحالات، القيام بكل هذا يدويًا (الربط بمقبض مأخذ التوصيل، أو مصفوفات العميل، وما إلى ذلك) ليس أمرًا مريحًا للغاية. لذلك، لكل مقبس هناك خاصية خاصة - البيانات. في الواقع، البيانات هي مجرد مؤشر. لذلك، عند كتابة بيانات العميل إلى هذه الخاصية، كن حذرًا واتبع قواعد العمل مع المؤشرات (تخصيص الذاكرة، تعريف النوع، وما إلى ذلك)!
إرسال الملفات عبر المقبس.
سننظر هنا في إرسال الملفات عبر مأخذ توصيل (بناءً على طلب JINX) :-). إذًا كيف يمكنك إرسال ملف عبر مأخذ توصيل؟ بسيط جدا! كل ما عليك فعله هو فتح هذا الملف كملف دفق (TFileStream) وإرساله عبر مأخذ توصيل (SendStream)! دعونا ننظر إلى هذا مع مثال:

(إرسال ملف عبر المقبس)

الإجراء SendFileBySocket(اسم الملف: سلسلة) ؛

فار srcfile: TFileStream;

يبدأ

(افتح اسم الملف)

Srcfile:= TFileStream.Create (اسم الملف,fmOpenRead) ;

(نرسلها إلى العميل المتصل الأول)

ServerSocket1.Socket.Connections[0].SendStream(srcfile);

(أغلق الملف)

Srcfile.Free ;

نهاية ؛

تجدر الإشارة إلى أن طريقة SendStream لا يتم استخدامها فقط من قبل الخادم، ولكن أيضًا من قبل العميل (ClientSocket1.Socket.SendStream(srcfile))
لماذا يمكن دمج عدة كتل في كتلة واحدة أثناء الإرسال؟
وهذا أيضًا بناءً على طلب JINX :-). شكرا جزيلا له على هذا! لذا، أولاً، تجدر الإشارة إلى أن البيانات المرسلة عبر المقبس لا يمكن دمجها في كتلة واحدة فحسب، بل يمكن أيضًا فصلها عبر عدة كتل. الحقيقة هي أن المقبس عبارة عن دفق عادي، ولكن على عكس، على سبيل المثال، دفق الملفات (TFileStream)، فإنه ينقل البيانات بشكل أبطأ (كما تفهم - الشبكة، وحركة المرور المحدودة، وما إلى ذلك). ولهذا أمران:
ServerSocket1.Socket.Connections.SendText("Hello, ");
ServerSocket1.Socket.Connections.SendText("world!");
متطابق تمامًا مع أمر واحد:
ServerSocket1.Socket.Connections.SendText("مرحبا بالعالم!");
ولهذا السبب، إذا قمت بإرسال ملف بحجم 100 كيلو بايت عبر مأخذ توصيل، فإن الشخص الذي أرسلت إليه هذه الكتلة سيتلقى عدة كتل بأحجام تعتمد على حركة المرور وازدحام الخط. علاوة على ذلك، فإن الأحجام لن تكون بالضرورة هي نفسها. ويترتب على ذلك أنه من أجل قبول ملف أو أي بيانات كبيرة أخرى، يجب عليك قبول كتل من البيانات ثم دمجها في وحدة واحدة (وحفظها، على سبيل المثال، في ملف). الحل الأمثل لهذه المشكلة هو نفس دفق الملف - TFileStream (أو دفق في الذاكرة - TMemoryStream). يمكنك تلقي أجزاء من البيانات من مأخذ التوصيل من خلال حدث OnRead (OnClientRead) باستخدام الأسلوب ReceiveBuf العالمي. يمكن تحديد حجم الكتلة المستلمة باستخدام طريقة CancelLength. يمكنك أيضًا استخدام دفق مأخذ التوصيل (راجع المقالة حول TClientSocket). وهنا مثال صغير (تقريبي):

(استلام الملف عبر المقبس)

الإجراء TForm1.ClientSocket1Read (المرسل: TObject؛

المقبس: TCustomWinSocket)؛

فار ل: عدد صحيح؛

بوف: PChar؛

Src: TFileStream;

يبدأ

(اكتب حجم الكتلة الناتجة)

L:= طول المقبس.

(اطلب الذاكرة للمخزن المؤقت)

GetMem (buf,l+1 ) ;

(اكتب الكتلة الناتجة في المخزن المؤقت)

المقبس.ReceiveBuf(buf,l);

(افتح ملفًا مؤقتًا للكتابة)

Src:= TFileStream.Create("myfile.tmp" ,fmOpenReadWrite) ;

(ضع الموضع في نهاية الملف)

Src.Seek (0 ,soFromEnd) ;

(اكتب المخزن المؤقت إلى ملف)

Src.WriteBuffer(buf,l);

(أغلق الملف)

Src.Free ;

(تحرير الذاكرة)

FreeMem(buf);

نهاية ؛

كيفية مراقبة المقبس
هذه القضية معقدة وتتطلب دراسة طويلة. في الوقت الحالي، سأشير فقط إلى أنه يمكنك دائمًا مراقبة المقبس الذي أنشأه برنامجك :-). المقابس (مثل معظم الكائنات في Windows) لها مقبض خاص بها، مكتوب في خاصية Handle. لذا، بمجرد التعرف على هذا الواصف، ستتمكن من إدارة أي مقبس بحرية (حتى تلك التي أنشأها برنامج شخص آخر)! ومع ذلك، على الأرجح، لمراقبة مأخذ توصيل شخص آخر، سيتعين عليك استخدام وظائف WinAPI مقبس حصريا.
الخاتمة
توضح هذه المقالة التقنيات الأساسية للعمل مع مكون TServerSocket في دلفي والعديد من التقنيات العامة لتبادل البيانات عبر المقابس. إذا كان لديك أسئلة، أرسلها لي عبر البريد الإلكتروني: [البريد الإلكتروني محمي]والأفضل من ذلك - الكتابة في مؤتمر هذا الموقع (أسئلة دلفي العامة) حتى يتمكن المستخدمون الآخرون من رؤية سؤالك ومحاولة الإجابة عليه!
كاريخ نيكولاي (نيترو). منطقة موسكو، جوكوفسكي

لقد أضفت دعم الشبكة. أي أنه قام بإنشاء خادم منفصل وعميل منفصل. الفكرة هي أن خادم التطبيق قيد التشغيل، ويقوم المستخدم بتشغيل العميل وإدخال الطلب في المستخدم: موسكو تفرسكايا 6. ثم يقوم الخادم بمعالجة الطلب، ويتلقى نتائج البحث من Yandex.Maps ويرسل الصورة الناتجة إلى العميل، ثم في العميل، يعرض مكون TMap جزءًا من بطاقة معينة تتوافق مع طلب المستخدم. ونتيجة لذلك، يمكن للمستخدم تغيير حجمه وحفظه وما إلى ذلك.

لذلك، أريد في هذه المقالة أن أخبرك كيف قمت بتنفيذ العميل والخادم. لقد قمت بذلك باستخدام TClientSocket و TServerSocket، في هذه المقالة سننظر بالتفصيل في الطرق التي استخدمتها في مشروعي.

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

للقيام بذلك، قم بتشغيل الأمر Component-Install Packages... وفي النافذة التي تظهر، انقر فوق الزر "إضافة". بعد ذلك، تحتاج إلى تحديد المسار إلى ملف dclsockets70.bpl، والذي عادة ما يكون موجودًا في مجلد BIN بشكل افتراضي. بعد هذا، تحتاج إلى النقر على زر موافق. يجب أن تظهر جميع مكوناتك في علامة التبويب "الإنترنت" (TClientSocket وTServerSocket).

في المشروع، بدأت كل العمل مع الحد الأدنى من تطوير الخادم. أولاً، قمت بتثبيت مكون TServerSocket في النموذج. ومن خلال النقر على زر ابدأ الخادم الذي قمت بتعيينه الإعدادات الأولية، لتهيئته:

الخادم. المنفذ:=FormServerSetting. SpinEditPort. قيمة ؛ // حدد منفذ الخادمالخادم. نشط: = صحيح؛ // تفعيله الخادم. يفتح ؛ إذا كان الخادم. نشط ثم تبدأ // عرض رسالة تفيد بأن الخادم قيد التشغيلنهاية ؛ …….. // عرض خطأ إذا لم يبدأ الخادم

لتهيئة الخادم على جهازي، قمت فقط بتحديد منفذ مجاني (لا تشغله تطبيقات أخرى) وقمت بتنشيطه.

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

من أجل الحصول على قائمة بالعملاء الذين يتصلون بالخادم ومواصلة العمل معهم، قمت بتثبيت مكون TCheckListBox في النموذج وفي حدث OnclientConnect لمكون TServerSocket، وكتبت الكود التالي:

الإجراء TFormServer. ServerClientConnect (المرسل: TObject؛ المقبس: TCustomWinSocket) ؛ يبدأ // مراقبة اتصال العميلسجل التحرير الغني. SelAttributes. اللون: = clGreen؛ سجل التحرير الغني. SelAttributes. النمط: = [fsBold]؛ CheckListClient. أغراض. Add(Socket.RemoteHost); سجل التحرير الغني. خطوط. إضافة ("[" + TimeToStr (Time ) + "] العميل متصل: " +ocket.RemoteHost ) ; // أضف العميل المتصل بالقائمةسجل التحرير الغني. تنفيذ (WM_VSCROLL، SB_BOTTOM، 0) ؛ نهاية ؛

أي أنني أضيف إلى القائمة أسماء هؤلاء العملاء الذين يتصلون بالخادم للحصول على معلومات إضافية عنهم.

على سبيل المثال، يمكنك الحصول على معلومات مفصلةعن العميل:

الإجراء TFormInfoClient. FormShow(Sender: TObject); يبدأ // عرض معلومات عن العميلالتسمية التوضيحية: = "معلومات العميل: "+فورمسيرفر. CheckListClient. العناصر[FormServer. CheckListClient. مؤشر الصنف ] ; الاسم المحلي. التسمية التوضيحية: = FormServer. الخادم. قابس كهرباء. اتصالات [FormServer. CheckListClient. فهرس العناصر] . المضيف المحلي ; مضيف محلي. التسمية التوضيحية: = FormServer. الخادم. قابس كهرباء. اتصالات [FormServer. CheckListClient. فهرس العناصر] . العنوان المحلي ; ميناء محلي. Caption: = IntToStr(FormServer.Server.Socket. Connections[ FormServer.CheckListClient.ItemIndex].LocalPort); اسم البعيد. التسمية التوضيحية: = FormServer. الخادم. قابس كهرباء. اتصالات [FormServer. CheckListClient. فهرس العناصر] . المضيف البعيد ؛ المضيف البعيد. التسمية التوضيحية: = FormServer. الخادم. قابس كهرباء. اتصالات [FormServer. CheckListClient. فهرس العناصر] . عنوان بعيد ؛ RemotePort. Caption: = IntToStr(FormServer.Server.Socket. Connections[ FormServer.CheckListClient.ItemIndex].RemotePort); نهاية ؛

ويمكن الحصول على البيانات التالية:

  • الاسم المحلي
  • العنوان المحلي
  • ميناء محلي
  • تمت إزالة الاسم
  • عنوان بعيد
  • المنفذ البعيد

أتلقى معلومات حول العميل باستخدام هذا الرمز الذي قمت بتحديده في قائمة مكون TCheckListBox.

كما ترون، لا يوجد شيء معقد، لإرسال رسالة إلى العميل، يمكنك استخدام الكود التالي:

في أقواس مربعة، أحدد العميل الذي سنرسل إليه الرسالة (وهذا يساوي العميل المحدد في مكون TCheckListBox)، أحدد #message# في الرسالة - مما يعني أن هذه رسالة عادية من الخادم والتي يجب عرضها ببساطة فى الشباك.

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

الإجراء TFormServer. ServerClientRead(Sender: TObject; المقبس: TCustomWinSocket) ; استعلام فار: سلسلة؛ يبدأ // تلقي طلب من العميل للحصول على البطاقةحاول الاستعلام: = المقبس. تلقي النص؛ إذا pos ("استعلام" ، استعلام)<>0 ثم ابدأ // طلب من ياندكس أو إحداثيات جوجلالبطاقات حسب طلب العميلنهاية ؛ // إذا كانت مجرد رسالة من العميل، فقم بعرضهاإذا pos ("#message#"، استعلام)<>0 ثم تبدأ النهاية ; ……

من هذا الرمز يمكنك أن ترى أنه يمكن للعميل إرسال رسالة عادية إلى الخادم وطلب الحصول على خريطة، مثل: موسكو، تفرسكايا، 6.

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

  • #رسالة#
  • #استفسار#

إذا كان معرف #message# موجودًا في بداية رسالة العميل، فسيتعرف عليه الخادم كرسالة عادية من العميل. في حالة وجود معرف #الاستعلام# في بداية الرسالة، فهذا يعني أن العميل قد أرسل طلبًا لاستلام البطاقة.

أيضًا، يمكن للعميل قطع الاتصال بالخادم في أي وقت، ونحتاج أيضًا إلى تتبع ذلك لإزالته من القائمة العامة للعملاء المتصلين بالخادم. للقيام بذلك، حدد مكون TServerSocket واكتب الكود التالي إلى حدث OnClientDisconnect:

الإجراء TFormServer. ServerClientDisconnect (المرسل: TObject؛ المقبس: TCustomWinSocket)؛ فار ط: عدد صحيح؛ ابدأ بالمحاولة // مراقبة قطع اتصال العميلسجل التحرير الغني. SelAttributes. اللون:=clRed؛ سجل التحرير الغني. SelAttributes. النمط: = [fsBold]؛ لأني : = 0 إلى الخادم. قابس كهرباء. ActiveConnections - 1 تبدأ إذا كان Server. قابس كهرباء. اتصالات [أنا]. المقبض = الخادم. قابس كهرباء. اتصالات [أنا]. قم بالتعامل مع ثم ابدأ RichEditLog. خطوط. إضافة ("[" + TimeToStr (Time ) + "] العميل غير متصل: " +ocket.RemoteHost ) ; CheckListClient. أغراض. يُحذف (ط)؛ سجل التحرير الغني. تنفيذ (WM_VSCROLL، SB_BOTTOM، 0) ؛ نهاية ؛ نهاية ؛ أخيرًا //-//-//-//-//-// النهاية ؛ نهاية ؛

نحن نتصفح جميع العملاء الموجودين في القائمة، وإذا لم نجد واحدًا، فإننا نقوم بإزالته من مكون TCheckListBox، وهذا يعني أن العميل قام بالنقر فوق زر قطع الاتصال في تطبيقه.




قمة