สรุปบทความ:
Delphi มีประสิทธิภาพมาก การเขียนซอฟต์แวร์ด้วย Delphi สามารถย่นระยะเวลาการพัฒนาซอฟต์แวร์ได้อย่างมาก บทความนี้จะแนะนำวิธีการใช้ Delphi เพื่อเขียนโปรแกรมถ่ายโอนไฟล์แบบจุดต่อจุด
-
Delphi มีประสิทธิภาพมาก การเขียนซอฟต์แวร์ด้วย Delphi สามารถย่นระยะเวลาการพัฒนาซอฟต์แวร์ได้อย่างมาก แนวคิดพื้นฐานของการถ่ายโอนไฟล์แบบจุดต่อจุดคือซอฟต์แวร์เซิร์ฟเวอร์และซอฟต์แวร์ไคลเอนต์ใช้พอร์ตเดียวกัน หลังจากเชื่อมต่อแล้วไคลเอนต์จะส่งคำขอไปยังเซิร์ฟเวอร์รวมถึงชื่อไฟล์ขนาด ฯลฯ ไฟล์ที่จะโอน หากเซิร์ฟเวอร์ยอมรับและเริ่มถ่ายโอนไฟล์ แน่นอนว่ามีสองโหมดสำหรับการถ่ายโอนไฟล์ รหัส ASCII และ Bin แต่โดยทั่วไป Bin ก็เพียงพอแล้ว จากการสนทนาข้างต้น เดิมทีสามารถทำได้โดยใช้ตัวควบคุม NMStrm และ NMStrmServ ของ Delphi4 แต่ฉันได้ทดสอบแล้วและพบว่าตัวควบคุม NMStrm ยังคงสามารถใช้กับไฟล์ขนาดเล็กได้และสะดวกมาก แต่ถ้าไฟล์มีขนาดใหญ่ (1M) จะเกิดข้อผิดพลาดขึ้น ต่อไปเราจะใช้ TServerSocket และ TClientSocket ใน Delphi เพื่อเขียนโปรแกรมนี้ เนื่องจากข้อจำกัดของขนาดแพ็กเก็ต Ethernet และกลไกการประมวลผลของ DelphiSocket (ใน Delphi เมื่อคุณใช้ Socket เพื่อส่ง Stream ที่ใหญ่กว่า ผู้รับจะทริกเกอร์ OnRead หลายครั้ง . เหตุการณ์ Delphi รับประกันความสมบูรณ์ของแต่ละข้อมูลในเหตุการณ์ OnRead หลายเหตุการณ์เท่านั้น และไม่ได้รวบรวมข้อมูลเองและส่งคืนให้กับผู้ใช้ ดังนั้นอย่าคิดว่าคุณจะสามารถส่งไฟล์เพื่อถ่ายโอนได้ครั้งเดียวใน Socket และ Recv เดียว ในอีกทางหนึ่ง คุณต้องรวบรวมข้อมูลด้วยตัวเองหรือกำหนดโปรโตคอลด้วยตัวเอง) ดังนั้นเราจึงใช้วิธีโปรโตคอลที่กำหนดเอง วิธีมาตรฐานในการกำหนดโปรโตคอลคือการใช้การสิ้นสุดการบันทึก ชอบ:
TMyFilePRotocol=บันทึก
sSendType=(ST_QUERY,ST_REFUSE,ST_DATA,ST_ABORT,...);
ความยาว:จำนวนเต็ม;
bufSend:บัฟเฟอร์;
จบ;
ฉันได้ลองใช้วิธีนี้แล้ว แต่ล้มเหลว และฉันคิดเสมอว่าวิธีการของฉันถูกต้อง แต่โปรแกรมไม่สามารถคอมไพล์ได้เสมอ ฉันเดาว่ามีบางอย่างผิดปกติกับ Delphi :) ดังนั้นฉันจึงใช้วิธีอื่นในโปรแกรมตัวอย่างต่อไปนี้ มีคุณสมบัติสองประการคือ GetText และ ReceiverBuf ในคลาส Socket ในเหตุการณ์ OnRead คุณสมบัติทั้งสองนี้สามารถใช้ได้เพียงครั้งเดียว ดังนั้นเราจึงสามารถใช้ตัวแปรส่วนกลางเพื่อบันทึกว่าจะอ่าน Text หรือ Buf กล่าวคือ อ่าน ส่งข้อความหนึ่งครั้งแล้วอ่านอีกครั้ง 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,
เอสเอส (TServerSocket)
btnStartServer.OnClick(ผู้ส่ง:TObject);
เริ่ม
เอสเอสพอร์ต:=2000;
เอสเอสเปิด;
จบ;
ss.OnClientRead (ผู้ส่ง: TObject; ซ็อกเก็ต: TCustomWinSocket);
var
sTemp:สตริง;
bufRecv:ตัวชี้;
iRecvLength: จำนวนเต็ม;
เริ่ม
ถ้า bReadText แล้ว
เริ่ม
sTemp:=Socket.ReceiveText;
กรณี sTemp[1] ของ
MP_QUERY:เริ่มต้น
//ปฏิเสธตรงนี้.
SaveDialog1.FileName:=คัดลอก(sTemp,2,ความยาว(STemp));
ถ้า SaveDialog1.Execute แล้ว
เริ่ม
ซ็อกเก็ต SendText (MP_ACCEPT);
fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
จบ
อื่น Socket.SendText (MP_REFUSE + 'ตาย');
จบ;
MP_FILEPROPERTY: เริ่มต้น
//หากต้องการส่ง StrToInt(Copy(sTemp,2,Length(sTemp))) ครั้ง
//แสดงความคืบหน้าของเวลา - -
ซ็อกเก็ต SendText (MP_NEXTWILLBEDATA);
จบ;
MP_NEXTWILLBEDATA:เริ่มต้น
ซ็อกเก็ต SendText (MP_DATA);
bReadText:=เท็จ;
จบ;
MP_END:เริ่มต้น
fsRecv.ฟรี
bReadText:=จริง;
จบ;
MP_ABORT:เริ่มต้น
fsRecv.ฟรี;
bReadText:=จริง;
จบ;
MP_CHAT:เริ่มต้น
//แชทข้อความ
จบ;
สิ้นสุด;{ของกรณี}
จบ
เริ่มอย่างอื่น
พยายาม
GetMem(bufRecv,2000);//2000 ต้อง >iBYTESEND
ซ็อกเก็ต.ReceiveBuf(bufRecv^,iRecvLength);
fsRecv.WriteBuffer(bufRecv^,iRecvLength);
ในที่สุด
FreeMem(bufRecv,2000);
สิ้นสุด;{ของความพยายาม}
bReadText:=จริง;
ซ็อกเก็ต SendText (MP_NEXTWILLBEDATA);
จบ;
จบ;
โปรแกรมไคลเอนต์:
วางตัวควบคุมต่อไปนี้: edtipAddress, OpenDialog1, btnConnect, btnSendFile,
cs (TClientSocket)
btnConnect.OnClick(ผู้ส่ง:TObject);
เริ่ม
cs.Address:=edtIPAddress.Text;
cs.พอร์ต:=2000;
cs.เชื่อมต่อ;
จบ;
btnSendFile.OnClick(ผู้ส่ง:TObject);
เริ่ม
ถ้า OpenDialog1.Execute แล้ว
เริ่ม
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);//ขนาดไฟล์???