Menggunakan Delphi untuk membangun server komunikasi dan pertukaran data - Analisis teknologi Transceiver (Bagian 2) Penulis: 火鸟 [email protected] 2. Penjelasan rinci tentang Layanan Transceiver 1. Ringkasan Analisis Layanan Transceiver Layanan Transceiver adalah komponen inti dari sistem Transceiver. Kernel Transceiver bertanggung jawab untuk membaca definisi dan parameter Port dan Channel yang ditetapkan oleh Konsol Transceiver dari perpustakaan konfigurasi sistem, secara dinamis membuat dan mengendalikan port komunikasi dan hubungannya selama runtime. , dan mengendalikan data. Penjadwalan penerimaan, pengiriman dan buffering, pengelolaan log dan antrian, dll. Transceiver Shell adalah implementasi semua jenis port yang didukung untuk pengiriman dan penerimaan data. 2. Ringkasan Desain Layanan Transceiver Layanan Transceiver dikembangkan dari aplikasi Layanan di Delphi. Aplikasi Layanan dapat berjalan dalam keadaan sistem, bukan dalam keadaan pengguna. Sistem operasi Service Control Manager (SCM) bertanggung jawab atas pengoperasian dan pengelolaan program. Layanan tidak memiliki antarmuka pengguna dan termasuk dalam program latar belakang. Kernel Transceiver adalah serangkaian metode kelas Transceiver yang menetapkan dan mengontrol Transceiver Shell, dan Transceiver Shell adalah kumpulan objek yang bertanggung jawab untuk komunikasi. Catatan: Karena pertimbangan kinerja dan beban, Kernel Transceiver hanya secara logis mengimplementasikan pembagian fungsional dalam diagram arsitektur, dan modul penyusunnya tidak diimplementasikan sepenuhnya berbasis objek. 3. Ringkasan Implementasi Layanan Transceiver i. Buat Aplikasi Layanan. Pilih NEW|Other... dari menu utama Delphi File... dan pilih NEW|Service Application di kotak dialog New Items yang muncul kerangka kerja adalah sebagai berikut: PROgram Project1; menggunakan SvcMgr, Unit1 di 'Unit1.pas' {Service1: TService};{$R *.RES}mulai Application.Initialize; Application.Run;end.unit Unit1;antarmukamenggunakan Windows, Pesan, SysUtils, Kelas, Grafik, Kontrol, SvcMgr, Dialog;ketik TService1 = class(TService) private { Deklarasi pribadi } fungsi publik GetServiceController: TServiceController; end;var Service1: prosedur TService1;implementasi{$R *.DFM} ServiceController(CtrlCode: DWord);stdcall;mulai Service1.Controller(CtrlCode);akhir;fungsi TService1.GetServiceController: TServiceController;mulai Hasil := ServiceController;end;end. Anda dapat melihat bahwa selain SvcMgr yang digunakan untuk manajemen layanan yang direferensikan di unit penggunaan, TService1 mewarisi dari TServiced alih-alih TForm, fungsi GetServiceController yang kelebihan beban dan proses ServiceController yang dipanggil dalam mode stdcall, ini dibuat dengan Delphi Tidak banyak yang istimewa dari program layanannya, Penggemar Delphi mungkin ingin bersorak lagi, inilah daya tarik Delphi RAD yang kuat. Selain itu, karena Aplikasi Layanan tidak dapat di-debug secara langsung saat runtime dan tidak memiliki antarmuka pengguna, keluaran informasi debug tanpa antarmuka harus dipertimbangkan selama pengembangan untuk memfasilitasi proses debug dan pemecahan masalah. ii. Untuk membuat kelas Pelabuhan yang memenuhi kebutuhan spesifik dan menggunakan Kernel Transceiver dengan mekanisme pengoperasian dan pemrosesan terpadu, Pelabuhan di Shell Transceiver diharuskan memiliki aturan pemrosesan terpadu lingkungan pengembangan (seperti TCP, FTP, dll.), dan ada pula yang tidak (seperti MSMQ, File, dll.). Misalnya: type//Karena tidak ada antarmuka pengguna, ini diwarisi dari TComponent dan bukan TControl TFilePort=class(TComponent) private FilePath:string;//Dapatkan atau simpan lokasi folder dari file Prefix:string;//File prefix suffix:string; //File suffix end; Setelah membuat kelas TFilePort, Kernel Transceiver dapat menggunakan metode pemrosesan kelas terpadu untuk mereferensikan dan mengelola objek guna mencapai tujuan mengakses file tertentu dari folder yang ditentukan oleh FilePath. Jika digunakan sebagai Sumber, file yang memenuhi syarat akan diperoleh dari folder tertentu. Jika digunakan sebagai Target, data yang diperoleh dari Sumber terkait akan ditulis ke file yang ditentukan (sebenarnya Parameter sebenarnya dari setiap objek Port berasal dari file tersebut. definisi tabel Port di perpustakaan konfigurasi sistem). Contoh lain: ketik TCOMPort=class(TComponent) private ComFace:string; //antarmuka COM untuk memperoleh atau mengirimkan data akhir TCOMPort akan digunakan untuk memperoleh data dari atau mengirimkan data ke antarmuka komponen COM yang ditentukan. Melakukan pemrosesan selanjutnya. Di Delphi, kelas OleVariant adalah salah satu cara untuk mengimplementasikan panggilan komponen COM. Kebutuhan menggunakan kelas TCOMPort adalah Transceiver akan membuat instance antarmuka COM yang ditentukan oleh TCOMPort ke dalam objek OleVariant hanya ketika akses data yang diperlukan diperlukan, dan objek tersebut diperlukan. akan dirilis setelah digunakan. , Hal ini dapat mengurangi tekanan beban pada Transceiver dan server COM. Pertimbangan yang sama berlaku untuk komponen serupa lainnya. Contoh kelas yang diberikan oleh penulis di sini hanyalah sebuah model, dan metode serta kejadian yang sesuai harus ditambahkan bila diperlukan. Kelas-kelas yang diimplementasikan penulis selama pengembangan antara lain: TCOMPort, TMSMQPort, TDBPort, TFilePort, dll.iii. Dukungan untuk banyak saluran - serangkaian objek yang mendeklarasikan Port. Transceiver menganggap proses komunikasi sebagai proses aliran data dari sumber ke target. Proses tersebut adalah Saluran di Transceiver, dan Saluran ini terdiri dari setidaknya dua. Terdiri dari dua port (satu untuk Sumber dan satu untuk Target), jadi jika Anda ingin menentukan jumlah Saluran yang tidak terbatas dengan Sumber dan Target digabungkan secara bebas, Anda harus mendeklarasikannya masing-masing untuk Sumber dan Target. Array objek dari berbagai kelas Port (dan buat hubungan yang sesuai untuk objek tersebut, seperti yang akan Anda lihat nanti). Misalnya: private { Deklarasi privat }TCPSource:array dari TServerSocket;//Array objek untuk Sumber TCP TCPTarget:array dari TClientSocket;//Array objek untuk Target TCP MailSource:array dari TIdPOP3; //Untuk array Objek Sumber Email MailTarget:array dari TIdSMTP; //Array objek untuk File Target EmailSumber:array dari TFilePort; //Array objek untuk File Sumber fileTarget:array dari TFilePort; //Array objek untuk File Target comSource:array dari TCOMPort; //Array objek untuk COM Sumber comTarget:array dari TCOMPort; Aturan pengoperasian pelabuhan untuk Sumber dan Target dengan tipe yang sama benar-benar berbeda, keduanya dianggap sebagai objek yang sangat berbeda dan tidak terkait langsung dalam konsep Transceiver. Oleh karena itu, untuk jenis Port yang sama, array objek juga dibuat secara terpisah sesuai Sumber dan Target. iv. Membuat instance array objek pada saat runtime. Jumlah elemen dalam setiap array objek dikelola oleh Port Builder pada saat runtime. Jika pengguna mendefinisikan beberapa jenis Port melalui Konsol Transceiver, Port Builder akan membuat instance-nya berdasarkan nomor dan nomornya. parameter masing-masing. Jika tidak, array objek tidak akan dipakai. Dalam objek Port tipe Sumber, properti Nama diatur ke bentuk 'Terima'+ID Port. Dalam pemicu penerimaan data berikutnya, ini akan membantu Petugas Data menemukan objek dan menjadwalkan berbagai jenis objek Port secara seragam. Atribut Tag digunakan untuk memberikan Pengontrol Saluran informasi ID target Saluran di mana ia berada. Berikut ini adalah bagian contoh array objek comSource di Port Builder mulai //Buat COM/ Terima Port itmp:=high(comSource)+1;// Dapatkan jumlah maksimum comSource saat ini, itmp adalah variabel integer SetLength(comSource ,itmp +1); // Tambahkan anggota array comSource comSource [itmp]:=TCOMPort.Create(self); // Buat instance anggota comSource[itmp].Name:= 'Receive'+inttostr(isource); //Setel atribut Nama ke 'Receive'+Port ID, dan isource adalah PortID saat ini dari tipe integer comSource [itmp].Tag:= itarget; Saluran tempatnya berada NullTest :=rece.Fields['Address'].value;//Dapatkan nilai konfigurasi sistem COMFace, NullTest adalah variabel Variant if (NullTest <>null) dan (trim(NullTest)<>'') lalu mulaicomSource [itmp].ComFace:=NullTest; //Tetapkan nilai yang valid ke ComFaceNullTest:=rece.Fields['interval'].value; //Dapatkan interval waktu pemicu untuk objek COM untuk mendapatkan data dalam konfigurasi sistem SetTimer(application.handle,isource,NullTest*60000 ,nil); //Menetapkan jam pemicu untuk Port saat ini untuk mengumpulkan data secara teratur, isource adalah Port IDendelsecomSource [itmp].Tag:=-1;//Inisialisasi gagal, ditandai sebagai Port end tidak valid; comSource adalah Port kelas Sumber yang digunakan untuk memanggil antarmuka yang ditentukan dalam ComFace dan memperoleh data setelah interval waktu tertentu, sesuai dengan comTarget Implementasinya adalah serupa, kecuali bahwa mengirimkan data ke ComFace dari comTarget adalah proses waktu nyata, jadi tidak perlu menggunakan interval pemicu, dan dua pernyataan untuk menetapkan jam dapat dihilangkan. Pembuatan dan inisialisasi objek Port jenis lainnya serupa. Misalnya, fragmen implementasi MailTarget lainnya: mulai //Buat SMTP/Kirim Port itmp:=high(MailTarget)+1; SetLength(MailTarget,itmp+1); itmp].Nama:='kirim'+ inttostr(itarget); MailTarget[itmp].Tag:=3;//Tetapkan sebagai identifikasi jenis Port Target NullTest:=rece.Fields['Address'].value; //Alamat server email if (NullTest <>null) dan (trim(NullTest) <>'') lalu MailTarget[itmp].Host :=NullTest lain bValid:=false; NullTest:=rece.Fields['Port'].value; //Port server email jika NullTest <>null maka(jika NullTest<>0 maka MailTarget[itmp].Port :=NullTest)else bValid:=false; =rece.Fields['user'].value;//Masuk nama pengguna jika NullTest <>null kemudianMailTarget[itmp].UserId :=NullTest else bValid:=false; NullTest:=rece.Fields['password'].value;//Kata sandi login………………………end;Mungkin Anda akan memiliki ini I Saya bingung. Sejumlah besar komponen komunikasi Transceiver Shell dibuat oleh Port Builder saat runtime. Apakah kinerja Layanan Transceiver akan tinggi? Faktanya, misi Port Builder selesai satu kali ketika peristiwa ServiceCreate terjadi. Jumlah Port Shell hanya akan mempengaruhi kecepatan inisialisasi Layanan Transceiver. Kecepatan komunikasi Port Shell dan kinerja Layanan Transceiver secara keseluruhan akan mempengaruhi Tentu saja, sumber daya sistem mungkin memerlukan lebih banyak waktu. v. Alokasi dinamis dan pemrosesan peristiwa Di antara beberapa port komunikasi yang didukung oleh Transceiver Shell, gunakan TServerSocket (Anda mungkin lebih cenderung menggunakan komponen komunikasi Indy, tetapi ini tidak melanggar ide desain Layanan Transceiver, ini hanya modifikasi di level Shell atau baru saja ditambahkan), TCPSource yang diimplementasikan lebih khas, karena TServerSocket, sebagai Port Sumber, berbeda dari objek seperti COM atau POP3 yang perlu dipicu secara teratur Layanan selalu dalam keadaan mendengarkan setelah dimulai. Ini adalah komponen yang menghasilkan peristiwa terkait ketika ClientSocket terhubung dan mengirim data. Berikut ini adalah fragmen contoh TCPSource: mulai //Buat TCP/Terima Port itmp:=high(TCPSource)+1;SetLength(TCPSource,itmp+1 TCPSource [itmp]:=TServerSocket.Create(self); [ itmp].OnClientRead:=TCPServersClientRead;//Tetapkan proses pemrosesan acara OnClientRead ke TCPServersClientRead TCPSource [itmp].OnClientError:=TCPServerClientError;//Tetapkan proses pemrosesan acara OnClientError ke TCPServerClientErrorTCPSource [itmp].Name:= 'Receive'+inttostr(isource); //Setel properti Nama ke 'Receive'+Port ID TCPSource [itmp ].Tag:=itarget; //Tetapkan target IDTCPSource Salurannya [itmp].Socket.Data:=@ TCPSource [itmp].Tag;//Lampirkan ID target objek Port ini ke objek Socket sebagai data penunjuk…………………end; Kembalilah dan lihat pemrosesan comSource kami. Selama pembuatan instance, kami menetapkan pemicu jam, tapi bagaimana menangani kejadian saat jam terpicu? Dengan cara yang sama, ini juga merupakan alokasi dinamis dari pemrosesan peristiwa. Definisi pemrosesan jam comSource dapat ditambahkan ke pemrosesan acara ServiceCreate: application.OnMessage:=Timer; untuk mengimplementasikan kelebihan pemrosesan pesan. Ketika pesan dari Aplikasi dibuat, Timer akan dipicu menyaring dan memprosesnya. Dengan pesan WM_TIMER yang dipicu oleh jam, Anda dapat memanggil metode akuisisi data dari Port Sumber tertentu sesuai dengan ID Port dan mengetik: Prosedur TCarrier.Timer(var Msg: TMsg; var Handled: Boolean);var stmp:string; Obj:TComponent;begin if Msg.message =WM_TIMER lalu//Memproses pesan jam dimulai//Temukan objek yang mendefinisikan pesan ini sesuai dengan ID Port yang memicu pesan Obj:=FindComponent( 'Receive'+inttostr (Msg.WParam)); if obj=nil lalu keluar;//Keluar dari pemrosesan jika tidak ditemukan stmp:=obj.ClassName;//Renungkan untuk mendapatkan informasi jenis objek Port ini jika stmp='TIdPOP3' lalu GetPOP3(TIdPOP3(Obj)); jika stmp='TIdFTP' maka GetFTP(TIdFTP(obj)); jika stmp='TFilePort' maka GetFile(TFilePort(Obj)); lalu GetCOM(TCOMPort(Obj));//Panggil proses akuisisi data COMSource........................ end;end; vi. Dapatkan data Berikut ini adalah prosedur pemrosesan akuisisi data COMSource TCarrier.GetCOM(COMObj: TCOMPort);var stmp:string; COMInterface:OleVariant;begin try//Buat objek komponen COM berdasarkan nilai dari ComFace COMInterface:=CreateOleObject (COMObj.ComFace); stmp:=COMInterface.GetData; //Panggil metode antarmuka yang disepakati untuk mendapatkan data saat stmp<>#0 do // #0 adalah tanda akhir ekstraksi data yang disepakati mulai DataArrive(stmp, COMObj.Tag); // diserahkan ke Dispatcher data untuk pemrosesan terpadu, COMObj.Tag adalah ID Port Target dari Saluran tempat objek berada stmp:=COMInterface.GetData; COMInterface:= Belum ditetapkan; kecuali COMInterface:= Belum ditetapkan; Selesaikan operasi ekstraksi data dan lepaskan objek komponen hingga panggilan pemicu berikutnya. Berikut ini adalah pemrosesan akuisisi data TCPSource: procedure TCarrier.TCPServersClientRead(Sender: TObject; Socket:TCustomWinSocket);beginDataArrive(socket.ReceiveText,integer(TServerWinSocket( pengirim).data ^));//Dispatcher data untuk pemrosesan terpadu, Parameter kedua adalah nilai pointer Target Port ID yang melekat pada objek Socket pengirim, akhir; berbagai jenis objek Sumber Port menerima data dengan cara yang berbeda, namun pada akhirnya data yang diterima diserahkan ke pemrosesan data Unified. Dari tingkat implementasi, setiap kali objek penerima data ditambahkan dan penerimaan datanya diimplementasikan, Port Sumber baru diimplementasikan untuk Transceiver Shell. Catatan: Penulis di sini hanya mengimplementasikan penerimaan data teks. Pengguna mungkin perlu menerima objek memori, aliran data, atau data biner, dan hanya membuat sedikit perubahan pada kode penerima. vii Penjadwalan Data Penjadwalan data Layanan Transceiver diselesaikan oleh unit logis Pengirim data. Tugas utama Pengirim Data adalah mengelola dan mengontrol data yang diterima dari Port Sumber yang berbeda secara seragam, dan bekerja sama dengan Pengontrol Saluran. Menurut Distribusi data Channel Define ke Port Target yang berbeda, pantau apakah hasil pengiriman berhasil, dan putuskan apakah data perlu diserahkan ke Manajer Antrean dan Perekam Log untuk buffering dan pemrosesan log berdasarkan hasil pengiriman dan pengaturan. dari perpustakaan konfigurasi sistem. Selanjutnya, lihat metode DataArrive dari Port Sumber yang mengirimkan data: procedure TCarrier.DataArrive(sData:String;PortID:Integer);var dTime:Datetime:integer; / Jika datanya kosong, keluarkan iLogID:=-1; dTime:= sekarang; //Terima waktu jika sData[length(sdata)]=#0 lalu sdata:=copy(sdata,1,length(sdata)-1);//Format string untuk kompatibilitas bahasa C bSendSeccess:=DataSend(sdata,PortID);//Panggil Data Dispatcher untuk mengirim metode pengiriman, PortID adalah ID Port Target jika (TSCfg.LogOnlyError=false) atau (bSendSeccess=false) theniLogID:=writeLog(dTime, sekarang,sData, PortID, bSendSeccess);//Rekam log sesuai dengan aturan pemrosesan log dan mengirimkan hasil dalam informasi konfigurasi sistem jika (TSCfg.Queueing=True) dan (bSendSeccess=false) lalu PutQueue(dTime, now,sData, PortID, bSendSeccess, iLogID) ; / /Tentukan akhir pemrosesan Antrian berdasarkan definisi konfigurasi Antrian dalam informasi konfigurasi sistem paket di atas adalah Data Metode DataArrive Dispatcher, di mana pemrosesan Antrean ditentukan berdasarkan informasi konfigurasi sistem dan status pengiriman, juga dapat disesuaikan dengan pemrosesan antrian wajib. Berikut ini adalah metode DataSend dari Data Dispatcher yang digunakan untuk mendistribusikan dan mengolah data sesuai dengan tipe Port Target: Function TCarrier.DataSend(sData:String;PortID:Integer):boolean;var Obj:TComponent;begin DataSend:=false ;Obj:=FindComponent ('Send'+inttostr(PortID)); //Temukan objek berdasarkan ID Port jika (obj=nil) atau (obj.Tag =-1) kemudian keluar;//Objek tidak ada atau telah ditandai sebagai tidak valid karena kegagalan inisialisasi. Port case obj.Tag dari 1:DataSend:=PutTCP(TClientSocket(obj),sdata); (obj), sdata); 5:Kirim Data:=PutFTP(TIdFTP(obj),sdata); 7:Kirim Data:=PutHTTP(TIdHTTP(obj),sdata); 9:Kirim Data:=PutFile(TFilePort(obj),sdata); 11:Kirim Data:=PutMSMQ(TMSMQPort (obj),sdata); PutDB(TDBPort(obj),sdata); 15:DataSend:=PutCOM(TCOMPort (obj),sdata); …………… …………… end;end; Perlu dicatat bahwa jika array objek tidak digunakan, tetapi hanya ada satu instance dari masing-masing array jenis Port Jika demikian, cara yang lebih baik untuk menangani distribusi data adalah dengan menggunakan fungsi panggilan balik, tetapi dalam kasus ini, hal itu akan menyebabkan tidak mengetahui anggota array objek mana yang harus menangani data. Selain itu, metode pemrosesan saat ini tidak sepenuhnya memisahkan Kernel Transceiver dan Shell Transceiver, dan kita harus mencari metode pemrosesan yang lebih abstrak dan independen. viii.Pengiriman data Berikut ini adalah fungsi pengiriman dari TCP TCarrier.PutTCP(TCPOBJ:TClientSocket;sdata:string):Boolean;var itime:integer;begin PutTCP:=false; gettickcount; //Waktu mulai ulangi application.ProcessMessages; sampai (TCPOBJ.Active=true) atau (gettickcount-itime>5000); //Lompat keluar dari loop jika koneksi berhasil atau batas waktu 5 detik terjadi jika TCPOBJ.Active kemudian mulai TCPOBJ.Socket.SendText(sdata); nilai pengembalian adalah ketika data berhasil dikirim. Trueend;TCPOBJ.Close; KecualiTCPOBJ.Close end;Berikut ini adalah fungsi pengiriman COM TCarrier.PutCOM(COMOBJ:TCOMPort;sdata:string):Boolean;var Com:OleVariant;begin PutCOM:=false; coba Com:=CreateOleObject(COMOBJ.ComFace);//Buat antarmuka yang telah ditentukan sebelumnya PutCOM:=Com.PutData ( sdata);//Panggil metode yang telah ditentukan Com:= Unassigned; kecualiCom:= Unassigned end; end; Jenis pengiriman Port lainnya serupa dan tidak akan diulangi di sini. Sejauh ini, pemrosesan dasar Sumber dan Target telah selesai. Fungsi komunikasi dasar telah ditetapkan. Setelah pencocokan bebas berbagai jenis Sumber dan Target, fungsi komunikasi yang sangat berbeda dapat diwujudkan. Dengan membuat beberapa Saluran, Anda dapat mengimplementasikan pemrosesan komunikasi secara terpusat untuk berbagai fungsi berbeda. ix. Pemrosesan antrian: Setelah data dikirim dalam metode DataArrive di atas, Data Dispatcher akan memanggil writeLog untuk pencatatan data dan metode PutQueue untuk pemrosesan antrian parameter sistem. Penyimpanan bukanlah fokus artikel ini. Proses Coba Ulang antrian serupa dengan prinsip mendistribusikan pemrosesan berdasarkan jenis Port dalam peristiwa Timer. Ini bergantung pada pemicu Timer Antrean untuk membaca data yang di-buffer dari database dan memanggil DataSend lagi sesuai dengan ID Port Target ke coba lagi pengiriman data, jika transmisi berhasil, transaksi transmisi data ini selesai, jika tidak maka akan masuk kembali ke antrian dan menunggu waktu pemicu berikutnya untuk mencoba lagi hingga transmisi berhasil atau jumlah percobaan ulang maksimum yang ditetapkan. tercapai. tiga, Ringkasan Pengalaman Pengembangan Karena fokus artikel ini adalah untuk menjelaskan ide inti dan konsep desain Transceiver, artikel ini menyederhanakan dan melemahkan pemrosesan multi-threading, pengumpulan objek, dan dukungan transaksi yang harus dipertimbangkan Transceiver sebagai layanan latar belakang, dan yang lebih kompleks dan Kelompok Sumber dan Sasaran yang kuat integrasi nnel, kemampuan mengirim dan menerima objek memori, aliran data, data biner, pembacaan informasi konfigurasi sistem dan implementasi kelas enkapsulasinya, keamanan sistem dan data, dll. Saya harap pembaca dapat memberikan beberapa wawasan dan memahami ide desain Transceiver. Menginspirasi percikan inspirasi dalam pekerjaan pengembangan aktual dan menciptakan perangkat lunak yang lebih luar biasa dan kuat. Penulis: Firebird [email protected] Gunakan Delphi untuk membuat server komunikasi dan pertukaran data—Analisis teknis transceiver (Bagian 1) Gunakan Delphi untuk membuat server komunikasi dan pertukaran data—Analisis teknis transceiver (Bagian 2) Menerapkan kelas pengumpulan melalui C# Ikhtisar . Koleksi NET dan hal-hal teknis lama terkait : pintasan program/penghapusan program/EXE menghapus sendiri Hal-hal lama DIY: catatan pengalaman algoritma pemrograman masa kecil