[الملخص] يعرف المبرمجون الذين كتبوا تطبيقات Winsock أن كتابة تطبيقات Winsock ليست مهمة سهلة بأي حال من الأحوال. يجب ألا تتعامل مباشرة مع واجهات برمجة التطبيقات المعقدة في Winsock، ولحسن الحظ، يقوم Tclientsocket وTserversocket في Delphi4 بتغليف واجهات برمجة التطبيقات ذات الصلة في Windows إلى حد كبير. إلى Winsock، مما يسمح لنا بكتابة تطبيقات Winsock بسهولة بالغة. يقدم هذا المقال كيفية كتابة تطبيقات Winsock باستخدام دلفي من خلال مثال لقراءة شاشة كمبيوتر آخر في الشبكة المحلية (LAN).
ربما يكون أي شخص عمل كمسؤول شبكة في مكان العمل قد مر بهذه التجربة. كم هو مزعج أن تطلب من الآخرين العمل عن طريق "التحكم عن بعد" عبر الهاتف، علاوة على ذلك، أنا شخص كسول ولا أريد الهروب من أعلى المبنى إلى الطابق السفلي لأمور تافهة كل يوم، ماذا تفعل؟ ماذا عن كتابة برنامج يقرأ شاشة كمبيوتر آخر؟ إنها أكثر سهولة. للتواصل داخل شبكة LAN، الخيار الأفضل هو بالطبع استخدام Winsock. يعرف المبرمجون الذين كتبوا تطبيقات Winsock أن كتابة تطبيقات Winsock ليست مهمة سهلة بأي حال من الأحوال، ويجب ألا تتعامل بشكل مباشر مع واجهات برمجة التطبيقات المعقدة في Winsock يقوم Tserversocket في Delphi4 بتغليف واجهات برمجة التطبيقات ذات الصلة في Windows، مما يبسط الوصول إلى Winsock إلى حد كبير ويسمح لنا بكتابة تطبيقات Winsock بسهولة بالغة. ومع ذلك، فمن الأفضل أن يكون لديك بعض الفهم لـ Winsock، ولن أخوض في التفاصيل هنا. يمكنك العثور على بعض الكتب وقراءتها بنفسك.
لنقل البيانات عبر الشبكة، تحتاج على الأقل إلى زوج من المقابس، أحدهما على العميل والآخر على الخادم. بمجرد قيام العميل ومقبس الخادم بإنشاء اتصال، يمكنهما التواصل مع بعضهما البعض تم تأسيسه على Tcp/ استنادًا إلى IP، كما أنه يدعم ipx/spx والبروتوكولات الأخرى ذات الصلة. في دلفي، يتم استخدام Tclientsocket وTserversocket للتحكم في الاتصال والاتصال بين العميل ومقبس الخادم. تجدر الإشارة إلى أنه يتم استخدام هذين المكونين لإدارة الاتصال بين الخادم والعميل، وهما ليسا كائنات مقبس بحد ذاتها. يتم التعامل مع كائنات المقبس بواسطة TcustomwinSocket، مثل Tclientwinsocket وTserverclientwinsocket.
1. مكون Tclientsocket:
عن طريق إضافة Tclientsocket إلى النموذج، يصبح التطبيق عميل Tcp/ip، ويمكن استخدام Tclientsocket لمعالجة كائن مأخذ التوصيل الخاص بالعميل.
لإنشاء اتصال بخادم، عليك أولاً تحديد الخادم الذي تريد الاتصال به. هناك طريقتان لتحديد الخادم. إحداهما هي تعيين سمة المضيف لتحديد اسم المضيف للخادم، مثل http://www.inPRise.com أو اسم الجهاز في الشبكة المحلية يتطلب تحليل اسم المجال، والذي سيكون أبطأ قليلاً؛ وهناك طريقة أخرى تتمثل في تعيين سمة العنوان لتحديد عنوان IP الخاص بالمضيف، مثل 130.0.1.1. الطريقتان متكافئتان، لكن إذا تم ضبط كل من المضيف والعنوان، فإن دلفي ستستخدم خاصية المضيف فقط.
ثم تحتاج إلى تحديد رقم المنفذ للاتصال بالخادم. هناك طريقتان هنا لتعيين الخدمة لاستخدام رقم المنفذ الافتراضي والأخرى هي تعيين رقم منفذ المنفذ مباشرة ، تم تخصيص العديد منها، مثل FTP، والمنافذ هي 20 و21، ومنفذ SMTP هو 25، ومنفذ خادم الويب هو 80، وما إلى ذلك. من أجل منع التعارضات غير المقصودة، يوصى عند برمجة التطبيق الخاص بك، بذلك من الأفضل ضبط المنفذ على 1024 أو أعلى. إذا تم ضبط الخدمة والمنفذ في نفس الوقت، فسوف تستخدم دلفي منفذ الخدمة الافتراضي.
بعد تحديد الخادم ورقم المنفذ، اتصل بالطريقة المفتوحة أو قم بتعيين السمة النشطة على True. سيقوم مقبس العميل بتقديم طلب اتصال إلى مقبس الخادم إذا كان الخادم في حالة الاستماع في هذا الوقت، فسوف يقبل تلقائيًا طلب إنشاء اتصال عند الاتصال، يتم تشغيل حدث Onconnet الخاص به. عندما تحتاج إلى قطع الاتصال، ما عليك سوى استدعاء طريقة الإغلاق أو تعيين السمة النشطة على False. في هذا الوقت، سيتم تشغيل حدث ondisconnet.
2. مكون Tserversocket:
مثل Tclientsocket، لإنشاء خادم، ما عليك سوى وضع مكون Tserversock في النموذج.
تعد إدارة كائن المقبس من جانب الخادم أكثر تعقيدًا. عندما يكون الخادم في حالة الاستماع، تتم معالجة كائن مأخذ التوصيل الخاص بالخادم بواسطة Tserversocket؛ عندما يقدم العميل طلبًا، يستجيب الخادم للطلب وينشئ اتصالاً المقبس ومقبس العميل.
لوضع الخادم في حالة الاستماع، يجب عليك أولاً تحديد رقم المنفذ، بالطبع، يجب أن يكون هو نفس رقم المنفذ الخاص بالعميل. ثم اتصل بالطريقة المفتوحة أو قم بتعيين الخاصية النشطة على True.
3. التواصل:
بمجرد إنشاء الاتصال بين العميل والخادم، يمكن أن يبدأ الاتصال مع بعضهما البعض. توفر دلفي عدة طرق اتصال لـ Tserversocket وTclientsocket. يُستخدم Sendtext لإرسال معلومات نصية، ويستخدم sendstream لإرسال التدفقات، ويستخدم SendBuf لإرسال بيانات ذات طول محدد.
تجدر الإشارة إلى أنه نظرًا لأن حجم المخزن المؤقت الافتراضي لنظام Windows هو 4K، عند إرسال معلومات أطول من 4K، على سبيل المثال، دفق ثنائي مرسل من الخادم إلى العميل، ما عليك سوى استخدام المقبس.SendStream() على الخادم. ولكن الأمر يختلف بالنسبة للعميل، فهو سيؤدي إلى تشغيل حدث onread عدة مرات، ولا تحدد دلفي أحداثًا مثل "onreadend"، لذلك يجب على المبرمج تجميع البيانات بنفسه عند الاستلام. الطريقة المعتمدة في هذه المقالة هي إرسال طول الدفق إلى العميل أولاً، ثم إرسال الدفق، ويكتب العميل البيانات المستلمة في الدفق أن العميل قد أكمل استلامه . بالنسبة للخادم، سيتم "ملكية" الدفق المستخدم كمعلمة sendstream بواسطة المقبس. عندما ينتهي كائن المقبس، سينتهي أيضًا.
وبالمثل، عندما يكون النص المرسل أقل من 4K، على سبيل المثال عند إجراء المكالمة التالية في برنامج العميل
Clientsocket1.Socket.SendText('gets');
Clientsocket1.Socket.SendText('gets');
Clientsocket1.Socket.SendText('gets');
عندما يتلقى الخادم، ستظهر ظواهر مثل getgets. قد يكون هذا لأنه عندما لم يتم إرسال البيانات الموجودة في المخزن المؤقت بعد، يتم وضع نص جديد في المخزن المؤقت، ويعامله الكمبيوتر على أنه نفس مجموعة البيانات للمعالجة. . ولتفادي حدوث هذه الظاهرة، يمكنك استخدام طريقة "رمي الكرة" ذهاباً وإياباً في البرنامج:
خادم العميل
Clientsocket1.Socket.SendText('data1') مقبس.ReceiveText;
المقبس.sendtext('موافق');
javascript.receivetext;
Clientsocket1.Socket.SendText('data2')
ReceiveText;
المقبس.sendtext('end');
javascript.receivetext;
بعد تشغيل برنامج الخادم على جهاز كمبيوتر آخر، أدخل اسم الكمبيوتر في مربع النص الموجود في برنامج العميل الخاص بك، وانقر فوق "اتصال"، ثم انقر فوق "الحصول على صورة"، وسيكون لديك رؤية واضحة لشاشة كمبيوتر الطرف الآخر. ما يلي هو الكود المصدري الكامل للبرنامج. يمكن تشغيل هذا البرنامج في NT4.0، وWin95، وWin98، وLAN. بالطبع، يجب أن يكون لدى Windows بروتوكول TCP/IP مثبتًا، ويجب أن يكون له عنوان IP معين أو محدد عنوان.
إذا وجدت صعوبة في "الأمر" أثناء المشاهدة، فيمكنك أيضًا تحليل أحداث لوحة المفاتيح والماوس على الصورة 1، ثم إرسالها إلى الخادم، وبعد أن يستقبلها الخادم، سيقوم بنفس العملية مرة أخرى، حتى لا تفعل ذلك لا داعي للقلق. باستخدام Tclientsocket وTserversocket من Delphi، يمكنك أيضًا إكمال تطوير التطبيقات مثل نسخ الملفات، والدردشة عبر الإنترنت، وICQ، وما إلى ذلك. ومن السهل جدًا تنفيذها، ويمكنك استخدام خيالك بحرية لكتابة برامج أكثر جاذبية.
برنامج العميل:
وحدة رئيسية؛
واجهة
الاستخدامات
Windows، الرسائل، SysUtils، الفئات، الرسومات، عناصر التحكم، النماذج، مربعات الحوار،
ScktComp، StdCtrls، ExtCtrls، jpeg؛
يكتب
TForm1 = الفئة (TForm)
اللوحة 1: لوحة T؛
ScrollBox1: TScrollBox؛
Image1: تيماج؛
Button1: TButton؛
تحرير 1: تحرير؛
Button2: TButton؛
ClientSocket1: TClientSocket;
التسمية 1: TLabel؛
الإجراء Button1Click(Sender: TObject);
الإجراء Button2Click(Sender: TObject);
الإجراء ClientSocket1Connect(Sender: TObject;
المقبس: TCustomWinSocket)؛
الإجراء ClientSocket1Error(Sender: TObject; المقبس: TCustomWinSocket;
ErrorEvent: TERrorEvent; var ErrorCode: Integer);
الإجراء ClientSocket1Read(Sender: TObject; المقبس: TCustomWinSocket);
الإجراء FormCreate(Sender: TObject);
الإجراء FormClose(Sender: TObject; var Action: TCloseAction);
خاص
{تصريحات خاصة}
عام
{التصريحات العامة}
نهاية؛
فار
Form1: TForm1؛
ج: لونجينت؛
م:تيميموريستريم؛
تطبيق
{$R *.DFM}
الإجراء TForm1.Button1Click(Sender: TObject);
يبدأ
يحاول
Clientsocket1.Close;
Clientsocket1.Host:=edit1.text;
Clientsocket1.Open; // الاتصال بالخادم
يستثني
showmessage(edit1.text+#13#10+'الكمبيوتر غير قيد التشغيل أو لم يتم تثبيت برنامج الخدمة');
نهاية؛
نهاية؛
الإجراء TForm1.Button2Click(Sender: TObject);
يبدأ
Clientsocket1.Socket.SendText('gets'); // أرسل طلبًا لإعلام الخادم بالحاجة إلى صورة الشاشة
نهاية؛
الإجراء TForm1.ClientSocket1Connect(Sender: TObject;
المقبس: TCustomWinSocket)؛
يبدأ
التسمية التوضيحية:='اتصل بـ'+edit1.text;
نهاية؛
الإجراء TForm1.ClientSocket1Error(Sender: TObject;
المقبس: TCustomWinSocket؛ ErrorEvent: TERrorEvent؛
varErrorCode: Integer);
يبدأ
التسمية التوضيحية:='الاتصال'+edit1.text+'فشل';
showmessage(edit1.text+#13#10+'الكمبيوتر غير قيد التشغيل أو لم يتم تثبيت برنامج الخدمة');
رمز الخطأ:=0;
نهاية؛
الإجراء TForm1.ClientSocket1Read(Sender: TObject;
المقبس: TCustomWinSocket)؛
فار
المخزن المؤقت: صفيف [0..10000] من البايت ؛ // تعيين المخزن المؤقت للاستقبال
لين:عدد صحيح؛
ليرة لبنانية: سلسلة؛
ب:tbitmap;
j:tjpegimage;
يبدأ
إذا كان c=0، فإن //C هو عدد البايتات التي يرسلها الخادم. وإذا كانت 0، فهذا يعني أن استقبال الصورة لم يبدأ بعد.
يبدأ
ll:=socket.ReceiveText;
c:=strtoint(ll); // قم بتعيين عدد البايتات التي سيتم استلامها
Clientsocket1.Socket.SendText('okok'); // قم بإخطار الخادم لبدء إرسال الصور
نهاية آخر
ابدأ // فيما يلي جزء استلام بيانات الصورة
len:=socket.ReceiveLength; // اقرأ طول الحزمة
المقبس.ReceiveBuf(buffer,len); //استلم حزمة البيانات واقرأها في المخزن المؤقت
m.Write(buffer,len); // إلحاق بالتيار M
إذا كان m.Size>=c ثم // إذا كان طول الدفق أكبر من عدد البايتات التي سيتم استقبالها، فهذا يعني أن الاستقبال قد اكتمل
يبدأ
م.الموقف:=0;
ب:=tbitmap.Create;
j:=tjpegimage.Create;
يحاول
j.LoadFromStream(m); // اقرأ البيانات الموجودة في الدفق M إلى كائن صورة JPG J
b.Assign(j); // تحويل JPG إلى BMP
Image1.Picture.Bitmap.Assign(b); // تعيين لمكون image1
أخيرًا // فيما يلي أعمال التنظيف
ب.مجاني؛
j.free;
Clientsocket1.Active:=false;
Clientsocket1.Active:=true;
م. واضح.
ج:=0;
نهاية؛
نهاية؛
نهاية؛
نهاية؛
الإجراء TForm1.FormCreate(Sender: TObject);
يبدأ
m:=tmemorystream.Create;
نهاية؛
الإجراء TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
يبدأ
م.مجاني;
ClientSocket1.Close;
نهاية؛
نهاية.
برنامج الخادم:
الوحدة الرئيسية
واجهة
الاستخدامات
Windows، الرسائل، SysUtils، الفئات، الرسومات، عناصر التحكم، النماذج، مربعات الحوار،
ScktComp,jpeg;
يكتب
TForm1 = الفئة (TForm)
ServerSocket1: TServerSocket؛
الإجراء ServerSocket1ClientRead(Sender: TObject;
المقبس: TCustomWinSocket)؛
الإجراء FormCreate(Sender: TObject);
خاص
{تصريحات خاصة}
عام
{التصريحات العامة}
نهاية؛
فار
Form1: TForm1؛
m1:tmemorystream;
تطبيق
{$R *.DFM}
الإجراء TForm1.ServerSocket1ClientRead(Sender: TObject;
المقبس: TCustomWinSocket)؛
فار
الصورة، s1: سلسلة؛
مكتب: قماش؛
الصورة النقطية: الصورة النقطية؛
jpg:tjpegimage;
يبدأ
s:=socket.ReceiveText;
إذا كان s='gets' ثم // يصدر العميل طلبًا
يبدأ
الصورة النقطية:=tbitmap.Create;
jpg:=tjpegimage.Create;
Desk:=tcanvas.Create; // الكود التالي هو الحصول على صورة الشاشة الحالية
Desk.Handle:=getdc(hwnd_desktop);
m1:=tmemorystream.Create // تهيئة الدفق m1، بعد إرسال الدفق باستخدام sendstream(m1)،
// سيبقى حتى تنتهي محادثة المقبس،
// لا يمكن تحريره يدويًا، وإلا سيتم تشغيل استثناء
مع الصورة النقطية تفعل
يبدأ
width:=screen.Width;
الارتفاع: = الشاشة. الارتفاع؛
Canvas.CopyRect(canvas.cliprect,desk,desk.cliprect);
نهاية؛
jpg.Assign(bitmap); // تحويل الصورة إلى تنسيق JPG
jpg.SaveToStream(m1); //اكتب صورة JPG في الدفق
jpg.free;
m1.Position:=0;
s1:=inttostr(m1.size);
المقبس.sendtext(s1); //أرسل حجم الصورة
نهاية؛
إذا s='okok' إذن // العميل جاهز لتلقي الصور
يبدأ
m1.Position:=0;
المقبس.SendStream(m1); //أرسل صورة JPG
نهاية؛
نهاية؛
الإجراء TForm1.FormCreate(Sender: TObject);
يبدأ
ServerSocket1.open;
نهاية؛
نهاية.