Chương 5
Lp trình ng d
ng
SNMP vi Delphi 2010
Chun b lp trình các phn mm SNMP
Thiết kế phn mm nhn trap : SNMP Trap
Receiver.
Thiết kế phn mềm giám sát lưu lượng thiết b :
SNMP Traffic Monitor
Thiết kế phn mm SNMP agent cho Windows
server, h tr ly các thông tin t to.
Abstract Syntax Notation One (ASN.1)
SNMP toàn tp
Chương 5
: L
p trình
ng d
ng SNMP v
i Delphi 2010
D I P T H A N H N G U Y Ê N , 2 0 1 0 T r a n g | 2
Chương này tác giả s trình bày cách viết các phn mm SNMP s dng ngôn ng lp trình Delphi phiên
bn 14 (Delphi 2010). Mc đích chương này trình bày ý tưởng tng bước trong vic viết các ng dng
SNMP hơn là trình bày pháp lp trình SNMP trên Delphi. Trên các ngôn ng khác thì ch khác nhau các
hàm khi to, gi, nhn bn tin, còn v trình t thc hin thì vn giống nhau. Các đoạn code ca tác gi
được viết mức đơn giản để th d dàng đọc hiu và chuyển đổi, nên chúng không phi là khuôn mu
tốc độ cao nht hay by li tt nht.
Source code ca toàn b các project có th download ti trang ch ca quyn tài liu này.
Ti sao bn cn phi lp trình SNMP ?
Nhiu thiết b, ng dụng được các hãng thiết kế mib riêng, bn không th giám sát chúng bng ng
dụng snmp thông thường. Bn th dùng phn mm ca chính hãng thiết b đó để giám sát. Nhưng nếu
bn nhiu chng loi thiết b khác nhau thì bt buc bn phi ng tng phn mm riêng. Bây gi làm
thế nào để dùng mt ng dng duy nhất để giám sát tt c chúng ? Lúc này bn cn biết cách lp trình ng
dng giám sát SNMP. Cũng một s phn mềm cho phép giám sát “custom mib” nhưng chưa hẳn chúng
đã đáp ứng hoàn toàn nhu cu ca bn.
Các thiết b gi các event dạng trap đến một trap host. Định nghĩa trap chuẩn ch mt s event rt
nghèo nàn, do đó các dòng sn phẩm khác nhau đều có định nghĩa rất nhiu trap enterpriseSpecific mà phi
dùng sn phm ca chính hãng mi th đọc được. Nếu bn file mib mô t event ca các thiết b, làm
thế nào để dùng mt ng dng duy nht để làm host nhn event và cnh báo cho tt c các chng loi thiết
b ? Lúc này bn cn biết cách lp trình ng dng SNMP Trap receiver.
Gi s bn viết mt ng dụng nào đó, ứng dng này chy trên rt nhiều server. Người qun tr cn giám
sát hiệu năng ng dng ca bn trên tt c các server mà không cn phi truy cp vào từng server để ly
thông tin. Bn th thiết kế giao thc và phn mềm giám t riêng, nhưng nếu s dng SNMP thì người
dùng th dùng các phn mm sẵn tính năng custom mib” như Solarwinds để giám sát ng dng ca
bn. c này bn cn biết cách lp trình ng dụng SNMP Agent để b sung tính năng này vào ứng dng ca
bn.
Nếu bn không phải là người phát trin ng dng, hoc vic dùng các phn mm giám sát sẵn đã đáp
ứng được nhu cu công vic thì bn không cn phải đọc chương này.
1. Chun b lp trình SNMP
Delphi 2010
Delphi là ngôn ng lp trình hướng đối tượng, pháp ging với Pascal. Môi trưng lp trình Delphi h
tr thiết kế form dng kéo th tương tự như Visual Studio. Các đối tưng giao diện được đóng gói gọi VCL
(Visual Component Library), tương tự như Controls trong C# hay Java Beans của Java. hàng trăm
component trong Delphi, và chúng h tr Unicode hoàn toàn. ng dng ca Delphi viết ra là ng dng
native Windows nên không s dng .NET Framework.
Bn cần cài đặt Delphi 2009 hoặc 2010 để viết các ng dng SNMP.
I ndy Project
Indy mt b thư viện các component h tr lp trình mng mc application (layer 7 trong mô hình
OSI), nghĩa là nhng gì ng dng ca bn phi x lý là phn data sau khi tách hết các header ca các giao
thc lp application. Indy h tr hu hết các giao thc ph biến như : TCP, UDP, IPMulticast, DNS, Echo,
FTP, HTTP, IMAP4, SMTP, POP3, Telnet, I CMP, Syslog, SNMP, . Bn th viết mt web server ch vi vài
dòng lnh.
Indy là mt d án mã ngun m đưc tích hp vào Delphi. Mã nguồn Indy được viết bng Delphi bi các
tình nguyn viên. 1
Nếu không s dụng thư viện Indy để viết ng dng mng, bn th s dng các component sn
trong Delphi là TTCPServer, TTCPClient, TUDPSocket để thay thế. Tuy nhiên lúc này bn phi t viết phn
mã x lý d liu các lớp cao hơn.
Và nếu không mun dùng nhng component ca Delphi na thì bn th ng các hàm Windows API
trong thư viện Winsock.
1 Trang ch Indy Project : http:// www.indyproject.org
SNMP toàn tp
Chương 5
: L
p trình
ng d
ng SNMP v
i Delphi 2010
D I P T H A N H N G U Y Ê N , 2 0 1 0 T r a n g | 3
Patch I ndy Tiburon
B Indy kèm theo Delphi 2010 li trong component IdSNMP, bn cn update n phiên bn mi nht
là Indy Tiburon để li, nếu kng IdSNMP s hoạt động sai. I ndy Tiburon th được download ti trang
ch quyn tài liu này hoc ti link gc http://indy.fulgan.com/ZI P/
Quá trình update thc cht là xóa bn Indy trong Delphi 2010 và thay thế bng bn Indy Tiburon, trình
t update như sau :
+ Gii nén bn Indy mi ra folder IndyTiburon.
+ Khởi động Delphi 2010.
+ M biên dch package IndyTiburon\ Lib\System\IndySystem140.dpk.
+ Biên dch package IndyTiburon\Lib\ Core\I ndyCore140.dpk.
+ Biên dch package IndyTiburon\Lib\ Core\dclIndyCore140.dpk.
+ Biên dch package IndyTiburon\Lib\ Protocols\IndyProtocols140.dpk.
+ Biên dch package IndyTiburon\Lib\ Protocols\dclIndyProtocols140.dpk.
+ Tt Delphi.
+ Xóa tt c file trong C:\ Program Files\Embarcadero\RAD Studio\ 7.0\lib\Indy10
+ Copy tt c các file * .dcu trong folder IndyTiburon (k c trong subfolder) sang C:\Program
Files\Embarcadero\RAD Studio\7.0\lib\Indy10 (khong 325 file).
+ Copy 5 file * .bpl trong C:\Users\Public\Documents\RAD Studio\7.0\ Bpl (Win 7) hoc C:\Documents and
Settings\All Users\Documents\RAD Studio\7.0\Bpl (Win XP) ghi đè vào các file trong folder C:\Program
Files\Embarcadero\RAD Studio\7.0\bin.
+ Khởi động li Delphi.
Lưu ý : phiên bn Indy ti thời điểm viết tài liu này là 10.5.5, mt phiên bn vẫn chưa hỗ tr
SNMPv2c. Do đó các ứng dụng được viết ch hoạt động đúng với SNMPv1.
2. SNMP Traffic Monitor
Gii thiu
SNMP Traffic Monitor là phn mm giám sát liên tc lưu lượng ca interface trên thiết b.
Các tính năng demo bao gồm :
+ Lấy đưc các thông tin mô t thiết b (nhóm mib-2.system).
+ Ly danh sách các interface và cho phép người ng chọn 1 interface để giám sát.
+ Cho phép chn các chu k ly mu khác nhau.
+ V lưu lưng ra biểu đồ, 2 đường lưu lưng in/out riêng, t động zoom biểu đồ khi lưu lượng tăng.
Do ch demo tp trung vào SNMP nên phn mm các hn chế sau :
+ Không giám sát được cùng c nhiu interface.
+ Không ghi nh kết qu giám sát, không in đưc biểu đồ.
Ý tưởng thc hin
Để ly thông tin v h thng (tên, mô t, thi gian hoạt động, ) ta ly tt c OID nằm dưới
.iso.org.dod.internet.mgmt.mib-2.system (.1.3.6.1.2.1.1).
Bn thân thiết b kng cung cp thông tin v tc độ lưu lượng ca interface nên ta không th ly trc
tiếp bng SNMP. Ta phi ly tng s byte interface đã nhn ti OID .iso.org.dod.internet.mgmt.mib-
2.interfaces.ifTable.ifEntry.ifInOctets (.1.3.6.1.2.1.2.2.1.10) và tng s byte đã truyn ti ifOutOctets
(.1.3.6.1.2.1.2.2.1.16). Vic lấy thông tin được thc hin liên tc và tính (giá_tr_sau
giá_trị_trước)/thi_gian_gia_các_ln_ly_mẫu để có được tốc độ lưu lượng ca interface.
Để không ảnh hưởng đến chương trình chính, phần code quét lưu lượng liên tục được đặt trong mt
thread.
SNMP toàn tp
Chương 5
: L
p trình
ng d
ng SNMP v
i Delphi 2010
D I P T H A N H N G U Y Ê N , 2 0 1 0 T r a n g | 4
Thiết kế giao din
Ly thông tin v thiết b
Sau khi nhp I P và community string, nhn t Lấy thông tin” để phn mm ly v các thông tin ca
thiết b trong nhóm mib-2.system như name, description, contact, ….
mmInfo.Clear;
SNMP.Host := edHost.Text;
SNMP.Community := edCommunity.Text;
SNMP.ReceiveTimeout := 1000; // timeout = 1000 ms
// Bước 1 : dùng hàm QuickSend để lấy các thông tin thuộc group mib-2.system
// mt số thiết bị không hỗ trợ sub-id nên ta ly cả 2 object sysDescr và sysDescr.0
// hàm QuickSend sẽ trả về TRUE nếu lấy thông tin thành công, FALSE nếu timeout
// kết quả lấy về là mt chuỗi chứa trong biến v
s := 'sysDescr : '; // sysDescr có oid là 1.3.6.1.2.1.1.1
if SNMP.QuickSend('1.3.6.1.2.1.1.1', SNMP.Community, SNMP.Host, v) or
SNMP.QuickSend('1.3.6.1.2.1.1.1.0', SNMP.Community, SNMP.Host, v) then s := s + v;
mmInfo.Lines.Add(s); // xuất kết quả ra mmInfo
s := 'sysUptime : ';
if SNMP.QuickSend('1.3.6.1.2.1.1.3', SNMP.Community, SNMP.Host, v) or
SNMP.QuickSend('1.3.6.1.2.1.1.3.0', SNMP.Community, SNMP.Host, v) then s := s + v;
mmInfo.Lines.Add(s);
s := 'sysContact : ';
if SNMP.QuickSend('1.3.6.1.2.1.1.4', SNMP.Community, SNMP.Host, v) or
SNMP.QuickSend('1.3.6.1.2.1.1.4.0', SNMP.Community, SNMP.Host, v) then s := s + v;
mmInfo.Lines.Add(s);
s := 'sysName : ';
if SNMP.QuickSend('1.3.6.1.2.1.1.5', SNMP.Community, SNMP.Host, v) or
SNMP.QuickSend('1.3.6.1.2.1.1.5.0', SNMP.Community, SNMP.Host, v) then s := s + v;
mmInfo.Lines.Add(s);
s := 'sysLocation : ';
if SNMP.QuickSend('1.3.6.1.2.1.1.6', SNMP.Community, SNMP.Host, v) or
SNMP toàn tp
Chương 5
: L
p trình
ng d
ng SNMP v
i Delphi 2010
D I P T H A N H N G U Y Ê N , 2 0 1 0 T r a n g | 5
SNMP.QuickSend('1.3.6.1.2.1.1.6.0', SNMP.Community, SNMP.Host, v)
then
s := s + v;
mmInfo.Lines.Add(s);
Các thông tin lấy được s đưc xut ra màn hình như ví dụ sau
Ly s lượng interface ca thiết b
Ly danh sách interface index
Ly thông tin ca interface
// Bước 2 : lấy tổng số interface đang có trên thiết bị
s := 'ifNumber : ';
if SNMP.QuickSend('1.3.6.1.2.1.2.1', SNMP.Community, SNMP.Host, v) or
SNMP.QuickSend('1.3.6.1.2.1.2.1.0', SNMP.Community, SNMP.Host, v) then s := s + v;
mmInfo.Lines.Add(s);
// nếu số ifNumber là rỗng hoặc không phải là kiểu số thì gán = 0
if not TryStrToInt(v, ifNumber) then ifNumber := 0;
// Bước 3 : Lần lượt lấy index của các interface entry, bằng cách GetNext liên tục, bắt
đầu từ ifIndex
SNMP.Query.Host := edHost.Text;
SNMP.Query.Community := edCommunity.Text;
SNMP.Query.Port := 161;
SNMP.Query.Version := 0; // s dụng SNMP v1 (0=v1; 1=v2c)
SNMP.Query.PDUType := PDUGetNextRequest;
List.Clear;
// ifIndex có OID là 1.3.6.1.2.1.2.1.1, khi GetNext sẽ lấy được ifIndex của interface
đầu tiên
OID := '1.3.6.1.2.1.2.1.1';
// vì tổng số interface của thiết bị = ifNumber nên ta lặp ifNumber lần
for i := 1 to ifNumber do
begin
SNMP.Query.MIBOID.Clear; // đầu tiên xóa sanh sách OID cần query
SNMP.Query.MIBOID.Add(OID); // sau đó thêm ifIndex của interface cần query
j := 1;
while (j<=3) and (SNMP.SendQuery=False) do inc(j); // nếu fail thì cho phép lp lại
đến lần thứ 3
if j <= 3 then begin
L := List.Items.Add; // thêm 1 dòng mi vào danh sách interface
L.Caption := SNMP.Reply.MIBValue[0]; // gán ifIndex vào Caption của ListItem
{ đặt OID = ifIndex của interface hiện tại, vòng lặp sau đó sẽ GetNext để
ly ifIndex của interface tiếp theo }
OID := SNMP.Reply.MIBOID[0];
end;
end;
// Bước 4 : lấy các thông tin khác ca từng interface
SNMP.Query.PDUType := PDUGetRequest;
for i := 0 to List.Items.Count - 1 do