دلفي قوية. يمكن أن تؤدي كتابة البرامج باستخدام دلفي إلى تقصير دورة تطوير البرامج بشكل كبير. الفكرة الأساسية لنقل الملفات من نقطة إلى نقطة هي أن برنامج الخادم وبرنامج العميل يستخدمان نفس المنفذ بعد الاتصال، يرسل العميل طلبًا إلى الخادم، بما في ذلك اسم الملف وحجمه وما إلى ذلك الملف المراد نقله إذا وافق الخادم وبدء نقل الملفات. بالطبع، هناك وضعان لنقل الملفات، رمز 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؟؟؟
نهاية؛
نهاية؛
cs.OnRead(Sender: TObject;Socket: TCustomWinSocket);
فار
درجة الحرارة: سلسلة؛
bufSend:pointer;
يبدأ
sRecv:=Socket.ReceiveText;
الحالة sRecv[1] من
MP_REFUSE:ShowMessage('خافت، سيتم رفضه!');
MP_ACCEPT: البدء
fsSend:=TFileStream.Create(OpenDialog1.FileName,fmOpen);
//iBYTEPERSEND ثابت، حجم الحزمة المرسلة في كل مرة.
Switch.SendText(MP_FILEPROPERTY+Trunc(fsSend.Size/iBYTEPERSEND)+1);
نهاية؛
MP_NEXTWILLBEDATA:البدء
المقبس.SendText(MP_NEXTWILLBEDATA);
نهاية؛
MP_DATA: البدء
يحاول
GetMem(bufSend,iBYTEPERSEND+1);
إذا (fsSend.Position+1+iBYTEPERSEND) <fsSend.Size ثم
يبدأ
fsSend.Read(bufSend^,iBYTEPERSEND);
//Socket.SendBuf(bufSend^,iBYTEPERSEND);
fsSend.Free;
end//إرسال عادي، الحجم iBYTEPERSEND
آخر تبدأ
fsSend.Read(bufSend^,fsSend.Size-fsSend.Position-1);
المقبس.SendBuf(bufSend^,fsSend.Size-fsSend.Position-1);
end;// آخر مرة يتم فيها الإرسال، أرسل البيانات المتبقية
أخيراً
FreeMem(bufSend,iBYTEPERSEND+1);
النهاية؛ {من المحاولة}
نهاية؛
MP_ABORT: البدء
// ملغى :(
fsSend.Free;
نهاية؛
النهاية؛ {من الحالة}
نهاية؛
إجراءات التنظيم:
إضافة حكم الخطأ، وتحسين البرنامج، والجمع بين الخادم والعميل، وإضافة عرض تقدم الوقت المتبقي، وإتاحة نقل ملفات متعددة في وقت واحد، وإضافة وظيفة الدردشة، ويصبح نقلًا جيدًا للملفات من نقطة إلى نقطة برنامج.