ملخص المقال:
دلفي قوية. يمكن أن تؤدي كتابة البرامج باستخدام دلفي إلى تقصير دورة تطوير البرامج بشكل كبير. تقدم هذه المقالة كيفية استخدام دلفي لكتابة برنامج نقل الملفات من نقطة إلى نقطة.
-----------------------------------------------
دلفي قوية. يمكن أن تؤدي كتابة البرامج باستخدام دلفي إلى تقصير دورة تطوير البرامج بشكل كبير. الفكرة الأساسية لنقل الملفات من نقطة إلى نقطة هي أن برنامج الخادم وبرنامج العميل يستخدمان نفس المنفذ بعد الاتصال، يرسل العميل طلبًا إلى الخادم، بما في ذلك اسم الملف وحجمه وما إلى ذلك الملف المراد نقله إذا وافق الخادم وبدء نقل الملفات. بالطبع، هناك وضعان لنقل الملفات، رمز ASCII وBin، لكن Bin بشكل عام يكفي. بناءً على المناقشة أعلاه، كان من الممكن في الأصل إجراء ذلك باستخدام عناصر التحكم NMStrm وNMStrmServ الخاصة بـ Delphi4، لكنني اختبرته ووجدت أنه لا يزال من الممكن استخدام عنصر التحكم NMStrm للملفات الأصغر حجمًا وهو ملائم للغاية، ولكن إذا كان الملف كبيرًا (1M) ، سيحدث خطأ. لذلك بعد ذلك نستخدم TServerSocket وTClientSocket في دلفي لكتابة هذا البرنامج. نظرًا لمحدودية حجم حزمة Ethernet وآلية المعالجة الخاصة بـ DelphiSocket (في دلفي، عندما تستخدم مقبسًا لإرسال دفق أكبر، سيقوم جهاز الاستقبال بتشغيل OnRead عدة مرات). . الحدث، دلفي تضمن فقط سلامة كل بيانات في أحداث OnRead المتعددة، ولا تقوم بجمع البيانات نفسها وإعادتها إلى المستخدم، لذلك لا تظن أنه يمكنك إرسال الملف ليتم نقله مرة واحدة في مقبس واحد وRecv مرة واحدة في مكان آخر، عليك جمع البيانات بنفسك أو تحديد البروتوكول بنفسك)، لذلك نعتمد طريقة البروتوكول المخصص. الطريقة الأساسية لتعريف البروتوكول هي استخدام Record End. يحب:
TMyFilePRotocol=سجل
sSendType=(ST_QUERY,ST_REFUSE,ST_DATA,ST_ABORT,...);
الطول:عدد صحيح؛
bufSend:Buffer;
نهاية؛
لقد قمت بتجربة هذه الطريقة، لكنها فشلت، واعتقدت دائمًا أن طريقتي كانت صحيحة، لكن البرنامج فشل دائمًا في التجميع، وأعتقد أن هناك خطأ ما في دلفي :) لذلك استخدمت طريقة أخرى في نموذج البرنامج التالي. هناك خاصيتان، ReceiveText وReceiveBuf، في فئة المقبس في حدث OnRead، لا يمكن استخدام هاتين الخاصيتين إلا مرة واحدة، لذا يمكننا استخدام متغير عام لحفظ ما إذا كنت تريد قراءة Text أو Buf، أي القراءة. قم بإرسال رسالة نصية مرة واحدة ثم قم بقراءتها مرة أخرى، وهذا يحاكي TMyFileProtocol.
ابدأ البرنامج:
اكتب أبسطها، والتي تستخدم بشكل أساسي لشرح الطريقة.
تعريف البروتوكول:
ثابت
MP_QUERY ='1';
MP_REFUSE ='2';
MP_ACCEPT ='3';
MP_NEXTWILLBEDATA='4';
MP_DATA ='5';
MP_ABORT ='6';
MP_OVER ='7';
MP_CHAT ='8';
مقدمة الاتفاقية:
أولاً، يرسل العميل MP_QUERY، وبعد استلامه، يرسل الخادم MP_ACCEPT أو MP_FEFUESE؛
يرسل العميل MP_FILEPROPERTY بعد استلام MP_ACCEPT، ويرسل الخادم MP_NEXTWILLBEDATA بعد استلامه؛
يرسل العميل MP_NEXTWILLBEDATA بعد استلامه، ويرسل الخادم MP_DATA بعد استلامه؛
يتلقى العميل MP_DATA ويرسل البيانات، ويتلقى الخادم البيانات ويرسل MP_NEXTWILLBEDATA؛
قم بالتكرار حتى يرسل العميل MP_OVER؛
يمكن إرسال MP_CHAT+String لبعضهما البعض في المنتصف؛
برنامج الخادم:
ضع عناصر التحكم التالية: SaveDialog1،btnStartServer،
سس، (تسفيرسوكيت)
btnStartServer.OnClick(Sender:TObject);
يبدأ
ss.Port:=2000;
ss.Open;
نهاية؛
ss.OnClientRead(Sender: TObject;Socket: TCustomWinSocket);
فار
درجة الحرارة: سلسلة؛
bufRecv:مؤشر;
iRecvLength:integer;
يبدأ
إذا bReadText بعد ذلك
يبدأ
sTemp:=Socket.ReceiveText;
حالة درجة الحرارة [1] من
MP_QUERY: البدء
// رفض هنا
SaveDialog1.FileName:=Copy(sTemp,2,Length(STemp));
إذا SaveDialog1.Execute بعد ذلك
يبدأ
المقبس.SendText(MP_ACCEPT);
fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
نهاية
elseocket.SendText(MP_REFUSE+'die');
نهاية؛
MP_FILEPROPERTY:البدء
// لإرسال StrToInt(Copy(sTemp,2,Length(sTemp))) مرات
// عرض تقدم الوقت. . .
المقبس.SendText(MP_NEXTWILLBEDATA);
نهاية؛
MP_NEXTWILLBEDATA:البدء
المقبس.SendText(MP_DATA);
bReadText:=false;
نهاية؛
MP_END:ابدأ
fsRecv.Free
bReadText:=true;
نهاية؛
MP_ABORT: البدء
fsRecv.Free;
bReadText:=true;
نهاية؛
MP_CHAT: البدء
// رسالة الدردشة
نهاية؛
النهاية؛ {من الحالة}
نهاية
آخر تبدأ
يحاول
GetMem(bufRecv,2000);//2000 يجب أن >iBYTESEND
المقبس.ReceiveBuf(bufRecv^,iRecvLength);
fsRecv.WriteBuffer(bufRecv^,iRecvLength);
أخيراً
FreeMem(bufRecv,2000);
النهاية؛ {من المحاولة}
bReadText:=true;
المقبس.SendText(MP_NEXTWILLBEDATA);
نهاية؛
نهاية؛
برنامج العميل:
ضع عناصر التحكم التالية: edtipAddress، OpenDialog1، btnConnect، btnSendFile،
CS.(TClientSocket)
btnConnect.OnClick(Sender:TObject);
يبدأ
cs.Address:=edtIPAddress.Text;
cs.Port:=2000;
cs.Connect;
نهاية؛
btnSendFile.OnClick(Sender:TObject);
يبدأ
إذا OpenDialog1.Execute بعد ذلك
يبدأ
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);//FileSize؟؟؟