Tải bản đầy đủ (.doc) (77 trang)

Bài tiểu luận môn học IP ứng dụng và bảo mật giới thiệu công cụ NS

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (632.79 KB, 77 trang )

1. Giới thiệu về cơngHỌ
cụCmơ
phỏ
g mạngNGHỆ
NS.............................................................4
VIỆ
N nCƠNG
VIỄN THƠNG
1.1 TởKHOA
ng quan....................................................................................................4
HỌ
C
VIỆ
N
CƠNG
NGHỆ
THƠNG
QUAN HỆ QUỐC TẾ VÀ ĐÀO VIỄ
TẠONSAU
ĐẠI HỌC
HỆn..................................................................................6
QUỐC TẾ VÀ ĐÀO TẠO SAU ĐẠI HỌC
1.2. Bộ KHOA
định trìQUAN
nh sự kiệ
1.3. Các thành phần mạng.................................................................................8
1.4. Gói dữ liệu................................................................................................10
2. Giao tiếp với bộ thông dịch: Liên kết OTcl..........................................................11
2.1 Các khái niệm............................................................................................11
2.2 Tổng quan về mã lệnh...............................................................................12
2.3 Lớp Tcl.......................................................................................................12


2.3.1 Lấy tham chiếu tới instance của lớp Tcl.............................................12
2.3.2 Gọi các hàm OTcl...............................................................................12
2.3.3 Gửi và nhận kết quả từ bộ thông dịch................................................12
2.3.4 Thông báo lỗi và thoát........................................................................13
2.3.5 Các hàm băm trong bộ thông dịch ....................................................13
2.4 Lớp TclObject............................................................................................13
2.4.1 Tạo và hủy đối tượng TclObject.........................................................13
IP – ỨNG DỤNG VÀ BẢO MẬT
2.4.2 Kết hợIP
p biế
........................................................................................14
–nỨ
NG DỤNG VÀ BẢO MẬT
2.4.3 Theo dõi giá trị biến............................................................................14
2.4.4 Hàm command: định nghĩa và cách gọi.............................................14
2.5 Lớp TclClass..............................................................................................14
2.5.1 Kết hợp các biến thành viên tĩnh của lớp C++..................................15
2.6 Lớp TclCommand......................................................................................15
2.7 Lớp EmbeddedTcl......................................................................................16
2.8 Lớp InstVar................................................................................................16
3. Lớp Simlator .........................................................................................................16
3.1 Khởi tạo bộ mô phỏng...............................................................................16
3.2. Bộ định trình và sự kiện...........................................................................17
3.2.1 Bộ định trình danh sách......................................................................18
Thầy hướng dẫn:
Hoàng Đăng Hải
3.2.2. Bộ định trình xếp đống......................................................................18
Học Viên:
Lê Đăng Phong [1-22]
3.2.3 Bộ định trình xếp hàng theo lịch........................................................18

Vũ Anh Tuấn [23-44]
3.2.4 Bộ định trình thời gian thực...............................................................18
Nguyễn Việt Thắng [45-66]
Đinh Hải Đăng [67-hết]
3.3 Các phương thức khác...............................................................................18
3.4. Lướt qua về các lệnh.................................................................................19
4. Các nút và chuyển gói............................................................................................20
4.1 Các cách thức của bộ mô phỏng: Tạo kiến trúc mạng..............................20
4.2 Các cách thức của nút: đặt cấu hình nút....................................................22
4.3 Cấu hình nút về mặt chức năng.................................................................23
4.3.1 Giao diện cấu hình nút........................................................................23
Hà Nợi
4.4 Bộ phân lớp................................................................................................25
4.4.1 Bộ phân lớp địa chỉ.............................................................................27

TIỂ
NNMƠN
TIỂUUḶ

MƠNHỌ
HỌCC

i


4.4.2 Bộ phân lớp đa hướng........................................................................27
4.4.3 Bộ phân lớp đa đường........................................................................28
4.4.4 Bộ phân lớp băm.................................................................................29
4.4.5 Bộ tạo bản sao.....................................................................................30
4.5 Module định tuyến và sự tổ chức bộ phân lớp..........................................31

4.5.1 Module định tuyến..............................................................................31
4.5.2 Giao diện nút.......................................................................................33
4.6 Xem qua một vài lệnh................................................................................34
5. Các liên kết: Các liên kết đơn ..............................................................................35
5.1. Thủ tục cho Links và SimpleLinks..........................................................36
5.2. Các Connector..........................................................................................37
5.3 Phân cấp đối tượng....................................................................................38
6. Quản lý hàng đợi và định trình gói.......................................................................39
6.1. Lớp Queue trong C++..............................................................................39
6.1.1 Khóa hàng đợi.....................................................................................40
6.1.2. Lớp PacketQueue...............................................................................42
6.2. Ví dụ: Loại bỏ phần cuối (Drop Tail)......................................................42
6.3 Các kiểu khác nhau của đối tượng Queue.................................................43
7. Trễ và các tuyến liên kết........................................................................................47
7.1 Lớp LinkDelay...........................................................................................47
8.Các dịch vụ trong ns...............................................................................................49
8.1. Tổng quan.................................................................................................49
8.2 Sự thi hành (Implementation)....................................................................50
8.2.1 Hàng đợi RED cho Diffserv...............................................................50
8.3 Cấu hình.....................................................................................................51
9. Agents..................................................................................................................... 52
9.1. Trạng thái Agent ......................................................................................52
9.2. Các phương thức của Agent.....................................................................52
9.3. Protocol Agents........................................................................................53
9.4. Liên kết trong OTcl .................................................................................54
9.4.1 Tạo và sửa đổi các Agent...................................................................54
9.4.2. Các giá trị mặc định...........................................................................54
9.4.3. Các phương thức trong OTcl.............................................................55
9.5. Ví dụ: Các agent Tcp, TCPSink...............................................................55
9.5.1. Tạo Agent..........................................................................................55

9.5.2. Khởi động Agent...............................................................................56
9.5.3. Xử lý đầu vào ở bộ thu......................................................................57
9.5.4. Xử lý đáp ứng ở bên gửi....................................................................58
9.5.5. Các bộ định thời.................................................................................59
9.6. Tạo một agent mới....................................................................................59

ii


9.6.1. Ví dụ: Yêu cầu “ping” (Cấu trúc kế thừa)........................................59
9.6.2. Các phương thức recv() và timeout()................................................60
9.6.3. Liên kết agent “ping” với OTcl.........................................................61
9.6.4. Sử dụng agent nhờ OTcl....................................................................62
9.7. Agent API.................................................................................................62
9.8. Các đối tượng agent khác.........................................................................62
9.9. Các lệnh cơ bản.........................................................................................63
10. Các bộ định thời...................................................................................................63
10.1. Lớp cơ sở trong C++ TimerHandler......................................................63
10.1.1. Định nghĩa một bộ định thời mới....................................................64
10.1.2. Ví dụ: Bộ định thời truyền lại TCP.................................................65
10.2. Lớp định thời trong OTcl.......................................................................68
10.3. Một số lệnh cơ bản.................................................................................68
11. Header gói và các định dạng...............................................................................68
11.1. Header gói cho một giao thức cụ thể......................................................69
11.1.1. Thêm một kiểu header gói mới.......................................................71
11.1.2. Lựa chọn các header gói trong bộ mơ phỏng .................................71
11.2. Các lớp gói..............................................................................................72
11.2.1. Lớp Packet.......................................................................................72
11.2.2. Lớp p_info.......................................................................................74
11.2.3. Lớp hdr_cmn...................................................................................74

11.2.4. Lớp PacketHeaderManager ............................................................75
11.3. Các lệnh cơ bản.......................................................................................77

iii


Giới thiệu công cụ NS

1. Giới thiệu về công cụ mô phỏng mạng NS
1.1 Tổng quan

NS là bộ công cụ mô phỏng mạng điều khiển theo các sự kiện rời rạc, được xây
dựng và phát triển bởi trường đại học Berkeley – Mỹ, cho phép mô phỏng nhiều kiểu
mạng IP khác nhau, mô phỏng các giao thức mạng: TCP, UDP cũng như các dạng
nguồn lưu lượng: FTP, Telnet, Web, CBR, VBR, mô phỏng các hàng đợi trong các bộ
định tuyến: DropTail, RED, CBQ, mô phỏng các giải thuật định tuyến. Ngoài ra NS
còn cho phép thực hiện việc phát đa luồng và một số giao thức lớp MAC đối với mô
phỏng LAN.
NS được xây dựng bằng ngôn ngữ lập trình hệ thống C++ và ngôn ngữ mô
phỏng OTcl. Otcl là dạng ngôn ngữ kịch bản Tcl được mở rộng theo mô hình hướng
đối tượng.

Hình 1: NS theo quan điểm người dùng
Theo quan điểm người dùng thuần túy, NS là một bộ thông dịch các kịch bản
Tcl hướng đối tượng. NS gồm có các bộ định trình các sự kiện mô phỏng, các thư viện
đối tượng thành phần mạng, thư viện các môdule tạo lập mạng (thực tế việc kết nối các
module được thực hiện bằng các hàm thành viên của các đối tượng mô phỏng cơ bản).
Khi sử dụng NS, người dùng phải lập trình bằng ngôn ngữ kịch bản Tcl. Để tạo
lập và triển khai một mạng mô phỏng, người dùng viết một kịch bản Tcl để khởi tạo
một bộ định trình sự kiện, thiết lập topo mạng thông qua việc sử dụng các đối tượng

thành phần mạng và các hành liên kết trong các thư viện của NS. Việc thiết lập một
mạng là ghép nối các đường dữ liệu giữa các đối tượng mạng bằng cách đặt con trỏ
của một đối tượng này tới địa chỉ của một đối tượng khác tương ứng. Khi muốn tạo
một đối tượng mạng mới, thì người dùng có thể tạo ra đối tượng đó bằng cách xây
dựng một đối tượng mới hoặc tổ hợp các đối tượng có sẵn trong các thư viện đối tượng
của NS và tạo ra các đường liên kết dữ liệu giữa chúng.
Một thành phần quan trọng của NS (bên cạnh các đối tượng mạng) là bộ định
trình sự kiện. Một sự kiện trong NS là một mã nhận dạng gói, mã này là duy nhất đối
với một gói, sự kiện được định thời và gắn với một con trỏ trỏ đến đối tượng sẽ xử lý
sự kiện đó. Trong NS, bộ định trình sự kiện giám sát toàn bộ thời gian mô phỏng, quản
lý và kích hoạt các sự kiện theo một hàng đợi. Khi một sự kiện được kích hoạt, bộ định
trình sẽ gọi tới thành phần đối tượng mạng xử lý tương ứng (thường cũng là đối tượng
Bài tiểu luận môn học IP-Ứng dụng và bảo mật

4


Giới thiệu công cụ NS
tạo ra sự kiện đó), cho phép đối tượng này thực hiện các tác vụ thích hợp lên gói gắn
với sự kiện. Các thành phần đối tượng mạng truyền thông với nhau bằng cách trao đổi
các gói. Về nguyên tắc, tất cả các thành phần mạng luôn cần phải có một khoảng thời
gian nhất định để xử lý gói (trễ). Trễ này được thể hiện thông qua việc sử dụng các bộ
định trình sự kiện: gửi đi một sự kiện gắn với gói và chờ sự kiện đó được kích hoạt trở
lại trước khi xử lý các gói tiếp theo. Ví dụ: một thành phần mạng mô phỏng một thiết
bị chuyển mạch gói với 20 ms trễ, nó sẽ gửi đi một sự kiện trễ 20 ms gắn với gói cần
phải chuyển mạch tới bộ định trình sự kiện, bộ định trình sau 20 ms sẽ đưa sự kiện đó
ra khỏi hàng đội và kích hoạt nó trở lại thành phần mạng chuyển mạch, thành phần
chuyển mạch sẽ thực hiện việc chuyển gói tương ứng tới đối tượng liên kết đầu ra của
nó.
Một ứng dụng nữa của bộ định trình sự kiện là tạo ra các bộ định thời. VD: giao

thức TCP cần bộ định thời để giám sát thời gian chờ khi phát đi một gói nhằm thực
hiện việc phát lại gói. Khi đó, bộ định thời sử dụng bộ định trình tương tự như trong
trường hợp giả lập trễ, sự khác biệt duy nhất là bộ định thời đo giá trị thời gian gắn với
một gói, thực hiện các tác vụ liên quan đến gói đó sau một khoảng thời gian nhất định
trôi qua mà không thực hiện việc mô phỏng trễ.
NS được viết bằng hai ngôn ngữ OTcl và C++. Để đảm bảo tính hiệu quả NS
phân chia đường dữ liệu và đường điều khiển riêng biệt. Để giảm thời gian chương
trình xử lý các sự kiện và gói (thời gian này không phải thời gian mô phỏng),thì bộ
định trình sự kiện và các đối tượng mạng cơ bản trong đường dữ liệu được viết và biên
dịch bằng ngôn ngữ C++. Các đối tượng sau biên dịch vẫn có thể được sử dụng bởi bộ
thông dịch Otcl thông qua các liên kết Otcl, các liên kết này tạo ra đối tượng OTcl
tương ứng cho mỗi đối tượng C++, cũng như tạo ra các hàm và các biến thành viên
trong đối tượng Otcl tương ứng với các biến và hàm thành viên trong đối tượng C++.
Bằng cách này việc điều khiển các đối tượng C++ có thể được thực hiện thông quan
OTcl, ngoài ra ta cũng có thể thêm các biến và hàm thành viên khác vào đối tượng
OTcl. Các đối tượng được viết bằng C++ mà không cần thiết phải điều khiển trực tiếp
trong quá trình mô phỏng cũng không cần phải liên kết sang OTcl.
Mặt khác một đối tượng không nằm trên đường số liệu có thể được xây dựng
hoàn toàn bằng OTcl. Hình 2 minh họa một cây phân cấp đối tượng trong C++ và
OTcl.

C++

OTcl
Hình 2: Sự tương đồng giữa C++ và OTcl

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

5



Giới thiệu công cụ NS

Hình 3: Mô hình kiến trúc của NS
Hình 3 chỉ ra kiến trúc chung của công cụ mô phỏng NS. Trong hình vẽ này,
người sử dụng thiết kế, triển khai các mô phỏng bằng các câu lệnh Tcl, sử dụng các đối
tượng mô phỏng từ thư viện Otcl, các bộ định trình sự kiện và phần lớn các đối tượng
mạng được xây dựng bằng C++, và các đối tượng này vẫn có thể được sử dụng như là
các đối tượng Otcl thông qua các liên kết. Toàn bộ các thành phần trong hình 3, kết
hợp lại tạo nên một bộ công cụ mô phỏng mạng NS, là một bộ thông dịch Tcl được mở
rộng hướng đối tượng và một tập các thư viện đối tượng mô phỏng mạng.
Các kết quả đạt được sau khi kết thúc quá trình mô phỏng, như trong hình vẽ 1,
là tập một hoặc nhiều file kết quả đầu ra dưới dạng văn bản text, chứa các dữ liệu mô
phỏng chi tiết. Các số liệu này có để được dùng để phân tích mô phỏng hoặc dùng làm
đầu vào cho các công cụ trình diễn mô phỏng mạng dạng đồ họa: Nam, Xgraph...
Nam (Network Animator) có dạng giao diện tương tự như một công cụ chơi
CD, cho phép hiển thị thông tin dạng đồ hoạc như: thông lượng, số gói bị loại bỏ trên
mỗi link ...
1.2. Bộ định trình sự kiện

Như đã đề cập đến ở phần trên, đối tượng sử dụng chính của các bộ định trình
sự kiện là các thành phần mạng, mô phỏng việc xử lý gói hoặc có sử dụng các bộ định
thời. Hình 4 mô tả các đối tượng mạng sử dụng bộ định trình sự kiện. Cần lưu ý rằng:
một đối tượng gửi đi một sự kiện nào đó cũng chính là đối tượng xử lý sự kiện đó tại
một thời điểm định sẵn và đường dữ liệu giữa các đối tượng khác với đường điều
khiển (đường sự kiện). Thực tế, việc đưa các gói từ một đối tượng mạng này đến một
đối tượng mạng khác được thực hiện bằng cách sử dụng hàm send(Packet *p)
{target_-> recv(p)} của đối tượng gửi và hàm recv(Packet *,
Handler * h =0) của đối tượng nhận.


Bài tiểu luận môn học IP-Ứng dụng và bảo mật

6


Giới thiệu công cụ NS

Hình 4: Bộ định trình sự kiện rời rạc
NS có hai kiểu định trình sự kiện khác nhau: định trình thời gian thực và định
trình không theo thời gian thực. Định trình không theo thời gian thực bao gồm 3 loại:
List, Heap và Calendar. Bộ định trình Calendar được sử dụng mặc định
trong NS. Các bộ định trình thời gian thực được sử dụng để thực hiện việc mô phỏng
tương tác với mạng thực tế.
Ví dụ: việc lựa chọn một bộ định trình sự kiện cụ thể được thực hiện như sau:
...
set ns [new Simulator]
$ns use-scheduler Heap
...

Một ứng dụng nữa của các bộ định trình sự kiện là tạo ra các bộ định thời sự
kiện mô phỏng như: khi nào thì bắt đầu một ứng dụng FTP, khi nào thì kết thúc mô
phỏng, hoặc để tạo ra các kịch bản mô phỏng trước khi thực hiện mô phỏng.
Một đối tượng định trình sự kiện , bản thân nó có các hàm thành viên định thời
mô phỏng, ví dụ như hàm at time "string" thực hiện phát đi sự kiện AtEvent
tại một thời điểm mô phỏng định sẵn: time. Sự kiện AtEvent đối tượng lớp con
của lớp Event, có một biến để chứa giá trị chuỗi string đã cho. Tuy nhiên sự kiện
AtEvent vẫn được xử lý bình thường như các sự kiện liên quan đến việc xử lý gói
khác trong bộ định trình sự kiện.
Khi một quá trình mô phỏng bắt đầu, và khi đến thời điểm định sẵn đối với sự
kiện AtEvent, sự kiện AtEvent được chuyển tới bộ xử lý sự kiện AtEvent, và

câu lệnh OTcl nằm trong chuỗi string của sự kiện AtEvent sẽ được thực thi. Ví dụ:
set ns [new Simulator]
$ns use-scheduler Heap
$ns at 300 "finish_sim"
...
proc finish_sim{}{
...
}

Trong ví dụ trên, ta thấy rằng hàm at time "string" là hàm thành viên của đối
tượng Simulator, nhưng cần phải lưu ý rằng đối tượng Simulator chỉ đóng vai trò giao
Bài tiểu luận môn học IP-Ứng dụng và bảo mật

7


Giới thiệu công cụ NS
tiếp người sử dụng, nên thực ra nó sẽ gọi đến các hàm thành viên của các đối tượng
mạng hoặc các đối tượng định trình để thực sự thực hiện công việc đó.
1.3. Các thành phần mạng

Trong NS, hầu hết các thành phần mạng là các đối tượng phức hợp. Hình 5 chỉ
ra một phần của cây phân cấp theo lớp OTcl.

Hình 5: Một phần của cây phân cấp theo lớp
Gốc của cây phân cấp này là lớp TclObject. Lớ
p TclObject là lớp cơ sở
của mọi đối tượng trong thư viện OTcl (định trình sự kiện, thành phần mạng, định thời,
và các đối tượng khác). Lớp NsObject là lớp cơ sở của mọi đối tượng thành phần
mạng cơ bản xử lý gói, các thành phần này kết hợp với nhau tạo thành các đối tượng

phức hợp, như các đối tượng nodes hoặc links chẳng hạn. Các thành phần mạng
cơ bản lại được chia thành hai phân lớp con, Connector và Classifier, dựa trên
số lượng đường dữ liệu đầu ra có thể. Các đối tượng mạng cơ sở chỉ có một đường dữ
liệu đầu ra duy nhất sẽ thuộc vào lớp Connector, các đối tượng chuyển mạch có thể
có nhiều đường dữ liệu đầu ra thuộc vào lớp Classifier.
Nút và định tuyến
Nút là một đối tượng phức hợp, được hợp thành bởi các đối tượng đầu vào nút
và các bộ phân loại classifier. Có hai loại nút trong NS. Nút đơn hướng chỉ có
một đối tượng phân loại địa chỉ thực hiện định tuyến đơn đường và một đối tượng
phân loại cổng. Nút đa hướng, ngoài hai đối tượng phân loại địa chỉ và phân loại cổng
như trong nút đơn hướng, còn có thêm một đối tượng phân loại gói đa hướng và một
đối tượng phân loại thực hiện định tuyến đa luồng.

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

8


Giới thiệu công cụ NS
Hình 6. Nút (đơn hướng và đa hướng)
Trong NS, các nút đơn hướng được sử dụng mặc định. Để tạo ra nút đa hướng,
người sử dụng phải khai báo tường minh trong kịch bản OTcl, ngay sau khi tạo ra đối
tượng định trình sự kiện, khi đó mọi nút được tạo ra sẽ là nút đa hướng. Sau khi chỉ ra
kiểu nút sử dụng, người sử dụng cũng có thể lựa chọn kiểu giao thức định tuyến xác
định thay vì sử dụng giao thức ngầm định.
Đường kết nối
Đường kết nối cũng là một đối tượng phức hợp chính khác trong NS, đối tượng
Link. Khi người sử dụng tạo ra một đường kết nối bằng cách sử dụng hàm thành viên
duplex-link của đối tượng Simulator, hai kết nối đơn trên hai hướng sẽ được tạo ra
như trong hình vẽ 7.


Hình 7: Đường kết nối
Cần lưu ý rằng hàng đợi đầu ra của một nút, thực ra là một phần của đối tượng
Link đơn. Các gói khi ra khỏi một hàng đợi Queue, sẽ được chuyển tới đối tượng
Delay, đối tượng này mô phỏng trễ của link, còn các gói bị loại bỏ khỏi hàng đợi
được gửi tới đối tượng Null Agent và được hủy tại đó. Cuối cùng, đối tượng TTL
tính toán tham số Time To Live đối với mỗi gói nhận được và thay đổi giá trị
trường TTL của gói.
Theo dõi giám sát
Trong NS, các tác vụ mạng được theo dõi trên mỗi đường kết nối đơn. Nếu đối
tượng mô phỏng được chỉ thị theo dõi các tác vụ mạng ( sử dụng lệnh $ns traceall file hoặc $ns trace-nam file), thì sau đó các đường kết nối được tạo ra
sẽ được thêm vào các đối tượng theo dõi như trong hình vẽ 8. Người sử dụng có thể
tạo ra đối tượng theo dõi thuộc một dạng nào đó giữa nút nguồn và nút đích bằng lệnh
create-trace {type file src dst}.

Hình 8. Các đối tượng theo dõi được thêm vào.
Khi mỗi đối tượng theo dõi nhận được một gói, nó sẽ ghi các thông số liên quan
đến gói ra file theo dõi mà không ảnh hưởng đến thời gian mô phỏng, và chuyển các
gói này tới đối tượng mạng tiếp theo.
Giám sát hàng đợi
Về cơ bản, các đối tượng theo dõi được thiết kế để ghi lại thời gian đến của gói
dữ liệu . Mặc dù người dùng có đủ các thông tin từ file theo dõi, nhưng có thể họ vẫn
Bài tiểu luận môn học IP-Ứng dụng và bảo mật

9


Giới thiệu công cụ NS
quan tâm đến những gì xảy ra bên trong một hàng đợi nào đó. Ví dụ: một người dùng
quan tâm đến cách thức xử lý một hàng đợi RED chẳng hạn, anh ta có thể muốn đo sự

thay đổi độ dài trung bình của hàng đợi và độ dài hiện thời của hàng đợi RED, điều đó
có nghĩa là cần phải giám sát hàng đợi đó.
Việc giám sát hàng đợi được thực hiện bằng cách sử dụng các đối tượng giám
sát hàng đợi và các đối tượng gián điệp như trong hình 10.

Hình 9: Giám sát hàng đợi
Khi một gói đến, đối tượng gián điệp sẽ thông báo cho đối tượng giám sát hàng
đợi và những thông tin này được sử dụng để giám sát hàng đợi.
1.4. Gói dữ liệu

Một gói trong NS được hình thành bởi một chồng các mào đầu, và một không
gian dữ liệu như hình 10

Hình 10: Khuôn dạng gói trong NS
Khuôn dạng mào đầu gói được tạo ra ngay khi đối tượng Simulator được khởi
tạo, bao gồm một tập tất cả các mào đầu đã đăng ký, chẳng hạn các mào đầu thường
được sử dụng: IP, TCP, RTP và các mào đầu theo dõi. Điều này có nghĩa là cho dù một
mào đầu cụ thể nào đó có được sử dụng hay không, thì một chồng gồm tất cả các mào
đầu đã đăng ký vẫn được tạo ra khi một gói được cấp phát bởi một đối tượng Agent,
và các đối tượng mạng có thể can thiệp tới bất kỳ mào đầu nào của gói.
Thường thì một gói chỉ có duy nhất một chồng mào đầu (và con trỏ không gian
dữ liệu được để bằng null). Mặc dù một gói có thể mang dữ liệu thực tế (từ một ứng
dụng nào đó) bằng việc cấp phát không gian dữ liệu, nhưng lại có rất ít ứng dụng và
Agent hỗ trợ việc này, bởi vì việc tải dữ liệu thực trong môi trường mô phỏng là điều
vô nghĩa. Tuy nhiên, nếu bạn muốn thực hiện một ứng dụng giao tiếp với một ứng
dụng khác qua mạng, thì có thể bạn muốn sử dụng đặc tính này với một chút sửa đổi
đối tượng Agent cơ sở.
Bài tiểu luận môn học IP-Ứng dụng và bảo mật

10



Giới thiệu công cụ NS

2. Giao tiếp với bộ thông dịch: Liên kết OTcl
NS là một công cụ mô phỏng hướng đối tượng, bao gồm bản thân NS là một
đối tượng được viết bằng C++ và một bộ thông dịch OTcl. NS hỗ trợ kiến trúc cây
phân cấp theo lớp trong C++ (cây phân cấp biên dịch) và kiến trúc cây phân cấp theo
lớp tương tự trong bộ thông dịch OTcl(cây phân cấp thông dịch). Hai cây phân cấp này
có quan hệ chặt chẽ với nhau. Từ góc nhìn của người dùng, tồn tại mối quan hệ 1-1
giữa một lớp trong cây phân cấp thông dịch và một lớp trong cây phân cấp biên dịch.
Gốc của cả hai cây phân cấp này là lớp TclObject. Người dùng sẽ tạo ra các đối tượng
mô phỏng thông qua bộ thông dịch, những đối tượng này, thuộc vào cây phân cấp
thông dịch, được khởi tạo trong bộ thông dịch và sẽ được ánh xạ sang một đối tượng
tương ứng trong cây phân cấp biên dịch.
Cây phân cấp thông dịch được tự động thiết lập thông qua các hàm được định
nghĩa trong lớp TclClass. Các đối tượng tạo bởi người dùng được ánh xạ thông qua các
hàm được định nghĩa trong lớp TclObject. Ngoài ra vẫn có các cây phân cấp khác
trong C++ và OTcl, đó là những cây thực sự không có quan hệ với nhau.
2.1 Các khái niệm

Trước hết ta tìm hiểu tại sao NS lại sử dụng hai ngôn ngữ C++ và OTcl. Đó là
bởi vì, trong quá trình thực hiện mô phỏng có hai việc khác nhau cần phải thực hiện:
Một mặt, việc mô phỏng chi tiết cề các giao thức đòi hỏi phải sử dụng một ngôn
ngữ lập trình hệ thống, nhằm xử lý hiệu quả với các dữ liệu dạng byte, các mào đầu
gói hay thực hiện các giải thuật tính toán trên một số lượng lớn dữ liệu. Đối với những
công việc như vậy thì tốc độ thực thi là rất quan trọng, còn thời gian thay đổi, nâng cấp
(quá trình chạy mô phỏng, tìm lỗi, sửa lỗi, biên dịch và chạy lại) sẽ ít quan trọng hơn.
Mặt khác, một phần lớn các công việc nghiên cứu mạng lại liên quan đến những
thay đổi nhỏ các tham số đầu vào, thay đổi cấu hình hay việc tìm hiểu nhanh chóng

một số mô hình mạng nào đó. Trong trường hợp này, thời gian lặp lại (thay đổi tham
số, cấu hình và chạy lại) lại trở nên quan trọng, còn thời gian thực thi sẽ ít quan trọng
hơn.
NS đáp ứng cả hai yêu cầu trên bằng cách sử dụng hai ngôn ngữ C++ và OTcl.
C++ có thời gian thực thi nhanh, nhưng chậm trong việc thay đổi nâng cấp, phù hợp
với việc triển khai chi tiết các giao thức hay xử lý gói. OTcl chạy chậm hơn nhưng lại
dễ dang thay đổi nhanh, phù hợp với việc thiết lập cấu hình mô phỏng. NS (thông qua
tclcl) đưa ra cơ chế cho phép sử dụng các đối tượng và biến trong môi trường cả hai
ngôn ngữ C++ và OTcl.
Mục đích sử dụng OTcl để:
- Thực hiện thiết lập cấu hình mô phỏng và những công việc chỉ thực hiện một
lần.
- Thực hiện những việc có thể giải quyết bằng cách tổ hợp các các đối tượng C++
và sử dụng C++ để:
- Thực hiện những công việc yêu cầu xử lý trên mỗi gói của luồng dữ liệu
- Sửa đổi những lớp C++ có sẵn
Ví dụ: links là những đối tượng OTcl, được lắp ráp từ các đối tượng C++: trễ,
xếp hàng, mất gói... Đối với những công việc yêu cầu xử lý chi tiết, cụ thể hơn
(nguyên lý hàng đợi hay một mô hình trễ đặc thù nào đó chẳng hạn) thì chúng ta sẽ
cần phải xây dựng một đối tượng C++ mới.

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

11


Giới thiệu công cụ NS
2.2 Tổng quan về mã lệnh

Chúng ta sử dụng thuật ngữ "bộ thông dịch" để nói đến thông dịch OTcl. Mã

giao tiếp với bộ thông dịch được đặt trong thư mục /tclcl và toàn bộ phần còn lại mã
mô phỏng được đặt trong thư mục NS-2.
Có một số lớp được định nghĩa trong thư mục /tclcl cho giao tiếp với bộ thông
dịch OTcl, chúng ta chỉ xem xét 6 lớp trong số đó được sử dụng trong NS:
- Lớp Tcl: chứa các hàm cho phép mã C++ truy nhập tới bộ thông dịch
- Lớp TclObject: là lớp cơ sở của tất cả các đối tượng mô phỏng
- Lớp TclClass: định nghĩa cây phân cấp thông dịch và các hàm cho phép
người dùng khởi tạo các đối tượng TclObject
- Lớp TclCommand: định nghĩa các câu lệnh thông dịch đơn giản
- Lớp EmbeddedTcl: định nghĩa các hàm để nạp các câu lệnh có sẵn ở múc
cao hơn, cho phép thiết lập câu hình mô phỏng dễ dàng hơn.
- Lớp InstVar: định nghĩa các hàm cho phép truy nhập tới các biến thành viên
C++.
2.3 Lớp Tcl

Lớp Tcl bao bọc toàn bộ instance thực sự của bộ thông dịch OTcl và đưa ra
các hàm giao tiếp với bộ thông dịch đó. Các hàm này cho phép thực hiện
- Lấy tham chiếu tới Tcl instance
- Gọi các hàm OTcl qua bộ thông dịch
- Nhận và trả lại kết quả cho bộ thông dịch
- Thông báo các tình huống lỗi và thoát
- Lưu tham chiếu và tìm các đối tượng TclObject
- Truy nhập trực tiếp tới bộ thông dịch
2.3.1 Lấy tham chiếu tới instance của lớp Tcl
Luôn tồn tại một instance duy nhất của lớp Tcl được khai báo như là một biến
thành viễn tĩnh, người lập trình có thể lấy được tham chiếu tới instance này qua câu
lệnh
Tcl& tcl = Tcl:instance()
2.3.2 Gọi các hàm OTcl
Có 4 hàm khác nhau để gọi một câu lệnh OTcl qua Tcl instance:

-

tcl.eval(char* s)
tcl.evalc(const char* s)
tcl.eval()
tcl.evalf(const char * s,..)

Những hàm này chỉ khác nhau ở tham số đầu vào, mỗi hàm sẽ chuyển câu lệnh
dưới dạng chuỗi tới bộ thông dịch, bộ thông dịch sẽ kiểm tra câu lệnh đó và trả về các
kết quả TCL_OK nếu câu lệnh đúng và TCL_ERROR nếu câu lệnh sai.
2.3.3 Gửi và nhận kết quả từ bộ thông dịch
Khi bộ thông dịch gọi các hàm C++, nó mong muốn kết quả được trả về trong
biến thành viên riêng tcl_->result. Có hai hàm để trả kết quả vào biến này là
-

tcl.result(const char * s)
tcl.result(const char * fmt,...)

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

12


Giới thiệu công cụ NS
Khi một hàm C++ thực hiện một câu lệnh OTcl, bộ thông dịch cũng sẽ trả kết
quả về trong biến thành viên riêng tcl_->result. Và để lấy được kết quả này sử
dụng hàm string tcl.result(void), hàm này trả về kết quả dưới dạng chuỗi.
2.3.4 Thông báo lỗi và thoát.
Hàm tcl.error(const char * s) được sử dụng để thông báo lỗi trong
mã biên dịch, nó thực hiện việc ghi chuỗi thông báo lỗi s cùng kết quả trả về

tclresult ra luồng stdout và thoát ra với mã lỗi bằng 1.
2.3.5 Các hàm băm trong bộ thông dịch
NS lưu tham chiếu của tất cả các đối tượng TclObject của cây biên dịch trong
một bảng băm. NS sử dụng tên của các đối tượng này để thêm vào, tìm kiếm hay xóa
tham chiếu của đối tượng trong bảng băm. Có 3 hàm để làm điều này
- tcl.enter (TclObject * o)
- tcl.lookup(char * s)
- tcl.remove(TclObject *o)
Các hàm trên được sử dụng trong nội tại các lớp TclObject và TclClass để quản
lý các đối tượng.
2.4 Lớp TclObject

TclObject là lớp cơ sở của phần lớn các lớp còn lại trong cây biên dịch và
thông dịch. Mỗi đối tượng thuộc lớp TclObject được tạo bởi người sử dụng thông
qua bộ thông dịch, và sẽ có một đối tượng ánh xạ tương ứng được tạo ra trong cây biên
dịch. Hai đối tượng này có quan hệ chặt chẽ với nhau. Lớp TclClass (được mô tả ở
phần sau) chứa các cơ chế cho phép thực hiện việc ánh xạ này.
2.4.1 Tạo và hủy đối tượng TclObject
Khi người dùng muốn khởi tạo hay xóa bỏ một đối tượng TclObject, hai hàm
new{} và delete{} sẽ được sử dụng để tạo và hủy các đối tượng này. Hai hàm
new{} và delete{} được sử dụng để tạo và hủy các đối tượng của tất cả các lớp
dẫn xuất từ lớp TclObject.
Tạo đối tượng TclObject: bằng cách dùng hàm new{}, người dùng sẽ tạo ra
một đối tượng TclObject thông dịch, bộ thông dịch thực hiện việc khởi tạo đối
tượng đó thông qua việc gọi hàm dựng init{} với các tham số nhận được từ người
dùng. Sau đó NS sẽ tự động tạo ra một đối tượng biên dịch tương ứng, đối tượng ánh
xạ này được tạo ra bởi hàm dựng của lớp TclObject cơ sở. Vì vậy để khởi tạo một đối
tượng TclObject, trước tiên cần phải gọi hàm dựng của lớp cha trước khi thực hiện các
khởi tạo đối tượng của lớp con. Hàm new{} trả về thẻ bài trỏ tới đối tượng được tạo
ra.

Hủy các đối tượng TclObject: việc này nhằm xóa bỏ đối tượng thông dịch và
đối tượng biên dịch ánh xạ tương ứng. Cũng giống như việc tạo đối tượng, khi hủy đối
tượng phải gọi hàm hủy của lớp cha một cách tường minh ở câu lệnh cuối cùng trong
hàm hủy của lớp con. Hàm hủy của đối tượng TclObject sẽ thực hiện gọi hàm
delete_shadow{} để xóa bỏ đối tượng biên dịch tương ứng. Cuối cùng bộ thông
dịch sẽ xóa bỏ đối tượng thông dịch

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

13


Giới thiệu công cụ NS
2.4.2 Kết hợp biến
Trong phần lớn các trường hợp, chúng ta không thể can thiệp trực tiếp vào các
biến thành viên biên dịch và việc can thiệp tới các biến thông dịch qua mã thong dịch
cũng rất hạn chế. Tuy nhiên, chúng ta có thể thiết lập nên sự kết hợp hai chiều: cả hai
biến thành viên biên dịch và thông dịch cùng truy nhập tới một dữ liệu duy nhất, sự
thay đổi giá trị của một trong hai biến thành viên sẽ làm thay đổi giá trị của biến thành
viên còn lại. Cơ chế kết hợp này thiết lập bởi hàm dựng biên dịch khi đối tượng được
khởi tạo.
NS hỗ trợ 5 loại dữ liệu khác nhau: kiểu thực, kiểu nguyên, kiểu logic, kiểu thời
gian và kiểu dữ liệu giá trị băng thông (Kb, Mb..). Cú pháp để thực hiện việc gán dữ
liệu cho các biến như sau
$object
$object
$object
$object
$object


set
set
set
set
set

realvar 1.2e3
intvar 123
bwvar 1.5mb
timevar 1500m
boolvar true

2.4.3 Theo dõi giá trị biến
Ngoài cơ chế kết hợp biến, TclObject còn hỗ trợ theo dõi giá trị của cả biến C+
+ và Tcl. Một biến khi được tạo ra trong C++ hoặc trong Tcl đều có thể thiết lập việc
theo dõi giá trị của nó. Để theo dõi giá trị một biến ở mức Tcl, thì biến đó phải xuất
hiện trong Tcl, điều đó có nghĩa là nó phải là một biến Tcl thuần túy hoặc là một biến
kết hợp C++/Tcl. Ngoài ra, một đối tượng có biến thành viên được theo dõi giá trị
cũng có thể yêu cầu việc theo dõi sử dụng hàm trace{} của đối tượng
TclObject.Hàm trace{} có hai tham số đầu vào, tham số vào đầu tiên là tên của
biến, tham số tùy chọn thứ hai chỉ ra đối tượng chịu trách nhiệm theo dõi giá trị của
biến cần theo dõi, nếu đối tượng theo dõi này không được chỉ ra, thì đối tượng sở hữu
biến sẽ chịu trách nhiệm theo dõi giá trị của biến.
Để một đối tượng TclObject có thể theo dõi được giá trị biến, nó phải mở rộng
hàm C++ trace(), đây là một hàm ảo đã được định nghĩa trong lớp TclObject.
2.4.4 Hàm command: định nghĩa và cách gọi
Đối với mỗi đối tượng TclObject được tạo ra, NS thiết lập một hàm mẫu
cmd{}, đóng vai trò như một giao tiếp để thực hiện các hàm của đối tượng biên dịch
ánh xạ. Hàm cmd{} tự động gọi hàm command() của đối tượng biên dịch, và các
tham số đầu vào của hàm cmd{} cho hàm command().

Người sử dụng có thể gọi hàm cmd{} theo hai cách: hoặc là gọi tường minh
hàm và chỉ ra tác vụ mong muốn ở biến đầu vào thứ nhất, hoặc gọi theo cách ngầm
định nếu tồn tại một hàm mẫu trùng tên với tác vụ mong muốn. Đa phần các kịch bản
mô phỏng đều sử dụng cách gọi thứ hai,
2.5 Lớp TclClass

Lớp biên dịch TclClass là một lớp ảo thuần túy. Các lớp được dẫn xuất từ lớp cơ
sở này có hai chức năng: xây dựng cây phân cấp theo lớp thông dịch để ánh xạ sang
cây phân cấp theo lớp biên dịch, và đưa ra các hàm để khởi khảo các đối tượng
TclObjects mới. Mỗi lớp dẫn xuất như vậy được gắn với một lớp biên dịch xác định

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

14


Giới thiệu công cụ NS
trong cây phân cấp biên dịch, và có thể khởi tạo các đối tượng mới của lớp biên dịch
tương ứng.
Ví dụ: chúng ta xem xét lớp RenoTcpClass, được dẫn xuất từ lớp TclClass, và
được gắn với lớp biên dịch RenoTcpAgent. Lớp RenoTcpClass sẽ khởi tạo các đối
tượng mới của lớp RenoTcpAgent. Lớp biên dịch RenoTcpAgent là lớp được dẫn xuất
từ lớp TcpAgent, bản thân lớp TcpAgent được dẫn xuất từ lớp Agent, và cuối cùng lớp
Agent lại được dẫn xuất từ lớp TclObject.
Lớp RenoTcpClass được định nghĩa như sau:
static class RenoTcpClass: public TclClass {
public:
RenoTcpClass() : TclClass("Agent/TCP/Reno") {}
TclObject* create(int argc, const char*const* argv) {
return (new RenoTcpAgent());

}
} class_reno;

2.5.1 Kết hợp các biến thành viên tĩnh của lớp C++
Ở phần trước, chúng ta đã đề cập đến cách thức để nhìn thấy các biến thành
viên của các đối tượng trọng C++ trong môi trường OTcl, tuy nhiên cơ chế này lại
không thể áp dụng cho các biến thành viên tĩnh của các lớp C++. Đương nhiên là,
chúng ta vẫn có thể tạo ra một biến trong OTcl tương ứng với biến thành viên tĩnh của
mỗi đối tượng C++, tuy nhiên điều này lại hoàn toàn phá hỏng đi ý nghĩa của biến
thành viên tĩnh.
Chúng ta không thể giải quyết vấn đề kết hợp biến này theo các giải pháp tương
tự như việc kết hợp biến trong TclObject, bởi vì cơ chế kết hợp biến trong TclObject
dựa trên lớp InstVar mà lớp này trong TclCl lại đòi hỏi sự hiện diện của một đối tượng
TclObject cụ thể. Tuy nhiên, chúng ta có thể tạo ra một hàm thuộc lớp TclClass tương
ứng và thực hiện việc truy xuất tới biến thành viên tĩnh của lớp C++ thông qua hàm
này. Các bước để thực hiện việc này như sau có thể tham khảo trong tài liệu hướng dẫn
NS, trang 30.
2.6 Lớp TclCommand

Lớp TclCommand đưa ra cơ chế cho phép NS chuyển các câu lệnh đơn giản tới
bộ thông dịch, và các câu lênh này có thể được thực hiện bởi bộ thông dịch trong môi
trường chung.
Có hai hàm: ns-random và ns-version thường được sử dụng trong môi
trường chung, cả hai hàm này được khởi tạo bởi hàm init_misc(void), và hàm
init_misc được gọi bởi hàm Tcl_AppInit(void) trong quá trình NS được nạp
vào bộ nhớ.
Lớp VersionCommand, định nghĩa hàm ns-version, hàm này không có
tham số đầu vào, và trả về phiên bản NS hiện thời dạng chuỗi.
Lớp RandomCommand, định nghĩa hàm ns-random, không tham số đầu vào,
trả về một giá trị nguyên ngẫu nhiên nằm trong khoảng [0, 231-1].

Ví dụ:
% ns-version
2.0a12
% ns-random
12334556
Bài tiểu luận môn học IP-Ứng dụng và bảo mật

15


Giới thiệu công cụ NS
2.7 Lớp EmbeddedTcl

NS cho phép phát triển các chức năng hoặc bằng mã biên dịch hoặc bằng mã
thông dịch, các mã này sẽ được kiểm tra khi khởi động NS. Chẳng hạn như các thư
viện mã ~tclcl/tcl-object.tcl, ~ns/tcl/lib/*.tcl. Việc nạp và kiểm tra các mã kịch bản này
sẽ được thực hiện thông qua các đối tượng trong lớp EmbeddedTcl.
Cách đơn giản nhất để mở rộng NS là thêm các mã OTcl hoặc là vào file tclobject.tcl hoặc vào các kịch bản trong thư mục ~ns/tcl/lib/. Cần lưu ý rằng, đối với
trường hợp thứ hai, NS nạp file ~ns/tcl/lib/ns-lib.tcl một cách tự động, vì vậy người
lập trình phải thêm vào file này hai dòng để đảm bảo kịch bản của mình được tự động
nạp vào lúc NS khởi động. Ví dụ để thêm vào kịch bản tcl/mcast/srm.tcl định nghĩa
các thủ tục cho phép chạy SRM, trong file ns-lib.tcl xuất hiện dòng lệnh
source tcl/mcast/srm.tcl

Có ba điểm cần lưu ý đối với mã EmbeddedTcl là: thứ nhất nếu trong quá trình
kiểm tra mã bị lỗi thì ns sẽ không chạy, thứ hai người sử dụng có thể ghi đè lên bất kỳ
đoạn mã nào trong thư viện mã, cụ thể là chúng có thể được thay đổi. Cuối dùng, sau
khi thêm các kịch bản vào ns-lib.tcl, cũng như mỗi lần sửa đổi sau đó, người sử dụng
phải biên dịch lại ns để những thay đổi đó có hiệu lực
2.8 Lớp InstVar


Lớp InstVar định nghĩa các hàm và đưa ra các cơ chế để kết hợp một biến
C++ trong đối tượng biên dịch với một biến OTcl xác định trong đối tượng thông dịch
tương ứng. Việc kết hợp này cho phép giá trị của biến có thể được thay đổi trong cả
hai môi trường: thông dịch và biên dịch ở mọi thời điểm.
Có
năm
lớp
biến:
InstVarReal,
InstVarTime,
InstVarBandwidth, InstVarInt và InstVarBool, được sử dụng để kết
hợp 5 kiểu biến: thực, nguyên, thời gian, logic và băng thông tương ứng.

3. Lớp Simlator
Tất cả bộ mô phỏng được mô tả bởi lớp Tcl của bộ mô phỏng. Nó cung cấp một
tập các giao diện cho việc đặt cấu hình mơ phỏng và lựa chọn kiểu của bộ định trình
sự kiện sử dụng để điều khiển việc mơ phỏng. Một kịch bản mơ phỏng nói chung bắt
đầu bởi việc tạo ra một lớp cụ thể và gọi các phương thức khác nhau để tạo các nút,
các cấu trúc liên kết mạng và cấu hình các khía cạnh khác của sự mô phỏng.
3.1 Khởi tạo bộ mô phỏng

Khi một đối tượng mô phỏng được tạo ra trong tcl, thủ tục khởi tạo được thực
hiện theo các thao tác:
- Khởi tạo định dạng gói (gọi hàm create_packetformat)
- Tạo bộ định trình (mặc định là bộ định trình lịch)
- Tạo một "tác tử rỗng"(null agent - nơi để hủy gói trong ở các ví trí khác
nhau)
Sự khởi tạo định dạng gói thiết lập các trường dư với các gói được sử dụng
trong suốt q trình mơ phỏng. Bộ định trình thực hiện mơ phỏng theo cách điều khiển

sự kiện và có thể được thay thế bởi bộ định trình luân phiên mà ở đó cung cấp một vài
ngữ nghĩa khác nhau (xem các phần dưới đây để có thêm chi tiết)

tác tử rỗng được tạo ra theo lời gọi:

set nullAgent_ [new Agent/Null]

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

16


Giới thiệu cơng cụ NS

Tác tử này nói chung là hữu ích như là một nơi để hủy gói hoặc như là
một cái đích cho các gói khơng được đếm hoặc được ghi lại.
3.2. Bộ định trình và sự kiện

Một bộ mô phỏng là một bộ mô phỏng điều khiển sự kiện, có 4 bộ định trình
hiện tại có trong bộ mô phỏng, chúng được thực hiện sử dụng cấu trúc dữ liệu khác
nhau: danh sách kết nối đơn, chất đống, hàng chờ lịch (mặc định) và một kiểu đặc biệt
được gọi là "thời gian thực". Mỗi chúng được mô tả dưới dây. Bộ định trình hoạt động
bởi việc lựa chọn sự kiện sớm nhất tiếp theo, thực hiện chúng cho tới khi hồn thành
sau đó quay trở lại thực hiện các sự kiện tiếp theo. Đơn vị thời gian được tính bởi bộ
định trình là giây. Hiện tại, bộ mô phỏng là tuyến đoạn đơn và chỉ một sự kiện được
thực hiện trong suốt thời gian. Nếu có hơn một sự kiện được định trình thực hiện ở
cùng một thời gian, sự hoạt động của chúng là được thực hiện theo cách định trình đầu
tiên được giải quyết đầu tiên, Những sự kiện đồng thời không được sắp xếp lại bởi bộ
định trình (như trong những phiên bản trước) và tất cả bộ định trình nên cung cấp cùng
mơt thứ tự giải quyết được đưa ra cho cung loại đầu vào.

Việc thực hiện từng phần các sự kiện hoặc các công việc được ưu tiên sẽ không
được hỗ trợ.
Một sự kiện nói chung gồm có "thời gian đốt cháy" (firing time) và một hàm
trình xử lý. Định nghĩa thật sự của một sự kiện như sau:
class Event {
public:
Event* next_; /* event list */
Handler* handler_; /* handler to call when event ready */
double time_; /* time at which event is ready */
int uid_; /* unique ID */
Event() : time_(0), uid_(0) {}
};
/*
* The base class for all event handlers. When an event’s scheduled
* time arrives, it is passed to handle which must consume it.
* i.e., if it needs to be freed it, it must be freed by the handler.
*/
class Handler {
public:
virtual void handle(Event* event);
};

Hai kiểu của đối tượng được dẫn xuất từ lớp sự kiện gốc: gói và "đang lúc sự
kiện" (at-event). Một at-event là việc thực hiện thủ tục tcl được định trình diễn ra tại
một thời điểm nhất định. Điều này thường xuyên được sử dụng trong kịch bản mơ
phỏng. Một ví dụ đơn giản về việc sử dụng chúng như sau:
...
set ns_ [new Simulator]
$ns_ use-scheduler Heap
$ns_ at 300.5 "$self complete_sim"

...

Đoạn mã tcl trên đầu tiên tạo ra đối tượng mơ phỏng, sau đó thay đổi bộ định
trình mặc định thành bộ định trình dựa trên việc tạo đống (xem bên dưới) và cuối cùng
định trình hàm $self complete_sim sẽ thực hiện ở thời gian 300.5s. Các at-event được
thi hành như các sự kiện mà trình xử lý thực hiện một cách hiệu quả của bộ thông dịch
tcl.
Bài tiểu luận môn học IP-Ứng dụng và bảo mật

17


Giới thiệu cơng cụ NS
3.2.1 Bộ định trình danh sách
Bộ định trình danh sách thực thi bộ định trình sử dụng cấu trúc danh sách liên
kết đơn. Danh sách giữ theo trật tự thời gian (sớm nhất đến muộn nhất) những sự kiện
chèn thêm vào và xóa đi yêu cầu qt danh sách để tìm ra mục thích hợp. Lựa chọn sự
kiện tiếp theo để thực hiện yêu cầu cắt mục đầu tiên ra khỏi đầu danh sách. Sự thực thi
này giữ cho việc thực hiện sự kiện theo cách FIFO cho các sự kiện đồng thời.
3.2.2. Bộ định trình xếp đống
Bộ định trình xếp đống thực thi bộ định trình sử dụng cấu trúc xếp đống. Cấu
trúc này là cao cấp hơn cấu trúc danh sách với số lượng lớn các sự kiện, như là thời
gian xóa và chèn thêm là O (log n) cho n sự kiện. Sự thực thi này trong ns v2 được lấy
từ bộ mô phỏng MaRS-2.0 bản thân MaRS lại được mượn mã từ bộ NetSim cho dù
dịng này
3.2.3 Bộ định trình xếp hàng theo lịch
Bộ định trình xếp hàng theo lịch sử dụng cấu trúc dữ liệu tương tự như lịch để
bàn 1 năm, ở đó các sự kiện cùng ngày tháng của các năm có thể được ghi trong một
ngày. Sự thực thi của xếp hàng theo lịch trong ns v2 được đóng góp bởi David
Wetherall

3.2.4 Bộ định trình thời gian thực
Bộ định trình thời gian thực cố gắng đồng bộ sự thi hành của các sự kiện với
thời gian thực. Nó thực thi như là một lớp con của bộ định trình danh sách. Khả năng
về thời gian thực trong ns là đang được phát triển, những đã được sử dụng đưa ra một
ns mô phỏng mạng trong kiến trúc thế giới thực được thực nghiệm với kiến trúc mạng
đơn giản, lưu lượng chéo, ... Nó chỉ hoạt động với tốc độ dữ liệu lưu lượng mạng
chậm, như một bộ mô phỏng cần phải có thể theo được với tốc độ đến của gói trong
thế giới thực, và sự đồng bộ này hiện tại là khơng có hiệu lực.
3.3 Các phương thức khác

Các lớp của bộ mô phỏng cung cấp một lượng các phương pháp sử dụng thiết
lập sự mô phỏng. Nói chung chúng được chia thành 3 loại:
Các phương pháp tạo, quản lý kiến trúc và quản lý các liên kết, các phương
pháp thực hiện việc theo vết, và trình giúp đỡ thực hiện chức năng xử lý với bộ định
trình. Theo đây là danh sách các phương pháp khơng có liên quan đến kiến trúc mạng
của bộ mơ phỏng:
Simulator instproc now ;# return scheduler’s notion of current time
Simulator instproc at args ;# schedule execution of code at specified
time
Simulator
Simulator
Simulator
Simulator
buffers
Simulator
object
Simulator
packet format

instproc cancel args ;# cancel event

instproc run args ;# start scheduler
instproc halt ;# stop (pause) the scheduler
instproc flush-trace ;# flush all trace

object

write

instproc create-trace type files src dst ;# create trace
instproc

create_packetformat

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

;#

set

up

the

simulator’s

18


Giới thiệu công cụ NS
3.4. Lướt qua về các lệnh

Synopsis:
ns <otclfile> <arg> <arg>..

Mô tả: Lệnh cơ bản để chay một kịch bản mô phỏng trong ns. Bộ mô phỏng ns
gọi thông qua bộ thông dịch ns, một sự mở rộng của lệnh vanilla otclsh. Sự mô phỏng
được định nghĩa bởi một kịch bản Otcl (tệp tin). Vài ví dụ về kịch bản Otcl có thể thấy
trong thư mục ns/tcl/ex
Dưới đây là danh sách chung nhất các lệnh của bộ mô phỏng được sử dụng
trong mô phỏng
scripts:
set ns_ [new Simulator]
lệnh này tạo ra một đối tượng cụ thể của bộ mô phỏng.
set now [$ns_ now]
Bộ đị nh trình giữ vết thời gian mơ phỏng. nó trả về thơng báo của bộ
đị nh trình về thời gian hiện tại.
$ns_ halt
dừng lại và tạm dừng bộ đị nh trình.
This stops or pauses the scheduler.
$ns_ run
Chạy bộ đị nh trình This starts the scheduler.
$ns_ at <time> <event>
Đị nh trình một sự kiện <event> (thơng thường là một đoạn mã) được
thực hiện ở một thời gian no ú.
e.g $ns_ at $opt(stop) "puts ăNS EXITING..ă ; $ns_ halt"
or, $ns_ at 10.0 "$ftp start"
$ns_ cancel <event>
Bỏ qua sự kiện, sự kiện được loại ra khỏi danh sách bộ đị nh trình của
những sự kiện sẵn sàng hoạt động.
$ns_ create-trace <type> <file> <src> <dst> <optional arg: op>
tạo một đối tượng giám sát kiểu <type> giữa đối tượng <src> và <dst>

và gán đối tượng giám sát này vào một tệp tin <file> để ghi lại kết quả
giám sát. Nếu op được đị nh ngh ĩ a là “nam”, nó tạo ra tệp tin giám sát nam;
nếu op không được đị nh ngh ĩ a các tệp tin giám sát ns được tạo ra một cách
tự động.
$ns_ flush-trace
Flushes all trace object write buffers.
$ns_ gen-map
kết xuất thông tin như các nút, các thành phần nút, liên kết, ...
được tạo ra từ sự mơ phỏng đã cho. Nó có thể phá vỡ vài ngữ cảnh (như khơng
dây)
$ns_ at-now <args>
có hiệu quả như lệnh "$ns_ at $now $args". Chú ý rằng chức năng này
có thể khơng hoạt động vì độ phân giải số ký tự của tcl.
$ns_ use-scheduler <type>
Sử dụng để ch ỉ ra kiểu của bộ đị nh trình được sử dụng khi mơ phỏng.
Kiểu của bộ đị nh trình có thể là List, Calendar, Heap và RealTime, hiện tại
bộ đị nh trình Calendar được sử dụng là mặc đị nh.
$ns_ after <delay> <event>
đị nh trình một sự kiện sẽ được thực hiện sau một khoảng thời gian
trễ.
$ns_ clearMemTrace
Sử dụng cho mục đích gỡ rối bộ nhớ.
$ns_ is-started
Trả về giá tr ị đúng nếu bộ mô phỏng đã chạy và trả về sại nếu không
chạy.
$ns_ dumpq
lệnh cho việc kết xuất các sự kiện được xếp hàng trong bộ đị nh trình
trong khi bộ đị nh trình treo.

Bài tiểu ḷn mơn học IP-Ứng dụng và bảo mật


19


Giới thiệu công cụ NS
$ns_ create_packetformat
Thiết lập đị nh dạng gói tin của bộ mơ phỏng.

4. Các nút và chuyển gói
Chương này mơ tả một khía cánh của việc tạo kiến trúc mạng trong ns như là
tạo các nút. Chương tiếp theo sẽ mơ tả khía cạnh thứ hai của việc tạo kiến trúc mạng
như là kết nối các nút thành các liên kết. Chương này ko mô tả chi tiết tổ chức bên
trong của một nút (cho dù một vài lược đồ được đưa ra), hoặc là tương tác giữa một
nút và module định tuyến của nó.
Nhắc lại rằng mỗi mô phỏng yêu cầu lớp của bộ mô phỏng cụ thể để điều khiển
và thao tác mô phỏng này. Lớp này cung cấp các thủ tục cụ thể để tạo và quản lý kiến
trúc mạng và lưu trữ bên trong các tham chiếu tới mỗi phần tử của kiến trúc mạng.
Chúng ta bắt đầu mô tả các thủ tục trong lớp Bộ mơ phỏng (phần 4.1) sau đó mơ tả các
thủ tục cụ thể trong lớp Node (phần 4.2) để truy cập và thao tác trên nút riêng biệt.
Chúng ta kết thúc với các mô tả chi tiết của Bộ phân lớp (phần 4.4) từ đó các đối
tượng nút phức hợp hơn được hình thành.
4.1 Các cách thức của bộ mô phỏng: Tạo kiến trúc mạng

Nguyên tố cơ bản có được một nút là:
set ns [new Simulator]
$ns node

Thủ tục cụ thể node dựng nên một nút từ các đối tượng phân lớp đơn giản hơn.
Bản thân Node là một lớp đứng độc lập trong OTcl. Hơn nữa, hầu hết các thành phần
của nút là trong đối tượng Tcl. Cấu trúc điển hình của một nút được chỉ ra trong hình

5.1
Trước ns phiên bản 2.1b6 địa chỉ của một tác tử trong một nút là rộng 16bit:
8bit cao được định nghĩa là node id_, 8 bit thấp nhận dạng tác tử riêng biệt trong nút.
Giới hạn số nút trong một lần mô phỏng là 256 nút. Nếu người sử dụng cần tạo một
kiến trúc mạng lớn hơn 256 nút thì đầu tiên cần phải mở rộng không gian địa chỉ trước
khi tạo bất cứ nút nào.

như là:
$ns set-address-format expanded

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

20


Giới thiệu cơng cụ NS

Hình 4.1: Cấu trúc của một nút đơn hướng, chú ý rằng entry_ là một biến sơ
nhãn đơn thay vì một đối tượng thật ví dụ như là classifier_
Mở rộng không gian địa chỉ tới 30 bit, 22 bít cao được sử dụng gán cho số nút.
Chú ý: Từ bản 2.1b6, trên đó thì khơng cần thiết dài hơn, ns sử dụng số nguyên
32 bit cho cả địa chỉ và cổng, cịn trước đó, giới hạn trên 256 nút là không thể dùng
được
Theo mặc định, các nút trong ns được dựng cho mô phỏng đơn hướng. Để mơ
phỏng đa hướng, sự mơ phỏng này có thể được tạo ra với lựa chọn "-multicast on", ví
dụ:
set ns [new Simulator -multicast on]

Cấu trúc bên trong của nút đa hướng được chỉ ra trong hình 5.2
Khi một mơ phỏng sử dụng định tuyến đa hướng, bit cao nhất của địa chỉ chỉ thị

rằng phần địa chỉ là địa chỉ đa hướng hay địa chỉ đơn hướng. Nếu bit đó là 0, địa chỉ
đại diện là đại chỉ đơn hướng, ngược lại là địa chỉ đa hướng. Nó ngụ ý rằng, theo mặc
định, mô phỏng đa hưởng được giới hạn trong 128 nút.

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

21


Giới thiệu cơng cụ NS

Hình 4.2 Cấu trúc bên trong của nút đa hướng
4.2 Các cách thức của nút: đặt cấu hình nút

Các thủ tục để cấu hình mỗi nút riêng biệt có thể được chia thành:
- Các chức năng điều khiển
- Quản lý số địa chỉ và số cổng, các chức năng định tuyến đơn hướng
- Quản lý tác tử
- Thêm lân cận
Chúng ta mô tả các chức năng như sau:

Các chức năng điều khiển:
$node entry trả về điểm đầu vào cho nút, đây là phần tử đầu tiên sẽ xử lý các
gói đến trong nút này.
Biến số cụ thể của Node, entry_, lưu tham chiếu phần tử này. Với nút đơn
hướng, đây là bộ phân lớp địa chỉ nhằm vào bit cao của địa chỉ đích. Biến số
classifier_ chứa tham chiếu tới bộ phân lớp này. Tuy nhiên, với các nút đa hướng,
điểm vào là biến switch_ nhằm vào bit đầu tiên để quyết hoặc là chuyển gói tới bộ
phân lớp đơn hướng hoặc là bộ phân lớp đa hướng cho phù hợp.
$node_reset sẽ xác lập lại toàn bộ tác tử của nút.


Quản lý địa chỉ và số cổng.
Thủ tục $node id trả về số id của nút, số này là tự động tăng và gán tới mỗi nút
tại lúc tạo nút bởi phương thức của bộ mô phỏng lớp, $ns node. Bộ mô phỏng lớp luôn
lưu trữ một mảng các biến cụ thể, Node_, được đánh chỉ mục bởi id của nút, chứa
tham chiếu tới nút bằng id này.
Thủ tục $node agent (port) trả về việc xử lý của tác tử tại cổng chỉ định, nếu
khơng có tác tử nào ở số cổng chỉ định là hợp lệ, thủ tục trả về chuỗi rỗng.
Thủ tục alloc-port trả về số cổng hợp lệ tiếp theo, nó sử dụng biến np_, để theo
dõi số cổng chưa được cấp phát kế tiếp.
Thủ tục add-route and add-routes, được sử dụng bở định tuyến đơn hướng và
cộng thêm các tuyến vào classifier_, cú pháp sử dụng là $node add-route (destination
Bài tiểu luận môn học IP-Ứng dụng và bảo mật

22


Giới thiệu công cụ NS
id) (TclObject). TclObject là đầu vào của dmux_, bộ giải ghép cổng của nút, nếu id
đích giống với id của nút này, nó thường là đoạn đầu của liên kết gửi gói cho điểm
đích, nhưng cũng có thể là đầu vào cho các bộ phân lớp khác hoặc kiểu của bộ phân
lớp.
$node add-routes (destination id) (TclObjects) được sử dụng để thêm vào nhiều
tuyến tới cùng một địa chỉ đích mà phải sử dụng đồng thời việc trải độ rộng băng
thơng theo cách quay trịn để đạt tới điểm đích từ bên này tới bên kia của tất cả các
liên kết một cách tương đương. Nó được sử dụng chỉ nếu biến số multiPath_ được gán
bằng 1, và chiến lược định tuyến động chi tiết là hiệu quả, cũng như yêu cầu sự sử
dụng của bộ phân lớp đa đường.
Đối lại với add-routes{} là delete-routes{} Nó lấy id, trong danh sách của
TclObjects và có tham chiếu tới nullagent của bộ mơ phỏng. Nó xóa TclObjects trong

danh sách từ các tuyến đã cài đặt trong bộ phân lớp đa đường. Nếu đầu vào của tuyến
trong bộ phân lớp không trỏ đến bộ phân lớp đa đường, thường lệ chỉ là xóa đầu vào từ
classifier_ và cài đặt nullagent vào chỗ đó.
Định tuyến động chi tiết cũng sử dụng 2 phương thức cộng thêm vào: thủ tục cụ
thể init-routing{} thiết lập biến số multiPath_ sẽ tương đương với biến số lớp cùng tên,
nó cũng cộng một tham chiếu tới đối tượng bộ điều khiển tuyến của nút trong biến số
này, rtObject_. Thủ tục rtObject{} trả về xử lý cho đối tượng tuyến của nút,
Cuối cùng, thủ tục intf-changed{} là được gọi lên bởi mã động trên mạng nếu
một liên kết rơi vào nút thay đổi trạng thái.
Quản lý tác tử
Một tác tử đã cho, thủ tục attach{} sẽ cộng thêm tác tử đó vào danh sách
agents_, gán số cổng của tác tử và đặt địa chỉ nguồn, đặt đích của tác tử cho nó và
cộng vào một con trỏ tới bộ giải ghép cổng của nút (dmux_) cho tác tử tại khe tương
ứng trong bộ phân lớp dmux_.
Ngược lại, detach{} sẽ xóa tác tử từ agent_, và chỉ đến đích của tác tử và đầu
vào nút dmux_ bằng nullagent.
Theo dõi nút lân cận (tracking Neighbors) Mỗi một nút giữ một danh sách các
nút lân cận nó trong biến neighbor_. Thủ tục add-neighbor{} cộng thêm một nút lân
cận vào danh sách. Thủ tục neighbors{} trả về danh sách này.
4.3 Cấu hình nút về mặt chức năng

4.3.1 Giao diện cấu hình nút
Giao diện cấu hình nút gồm có 2 phần. Phần thứ nhất giải quyết cấu hình nút,
phần thứ 2 thực sự tạo ra nút theo kiểu cụ thể. Cấu hình nút gồm có định nghĩa các đặc
tính khác nhau của nút trước khi tạo ra chúng, có thể gồm có kiểu cấu trúc đánh địa chỉ
trong việc mô phỏng, định nghĩa các thành phần mạng cho các nút di đông, bật hoặc
tắt các lựa chọn theo dõi ở mức tác tử, bộ định tuyến hoặc MAC, lựa chọn kiểu các thủ
tục định tuyến thay đổi cho các nút không dây hoặc định nghĩa mơ hình năng lượng
của chúng. Tồn bộ API cấu hình nút như sau:
OPTION_TYPE AVAILABLE OPTION_VALUES

------------- -------------------------$ns_ node-config -addressingType flat or hierarchical or expanded
-adhocRouting DSDV or DSR or TORA or AODV
-llType LL
-macType Mac/802_11
-propType Propagation/TwoRayGround

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

23


Giới thiệu công cụ NS
-ifqType Queue/DropTail/PriQueue
-ifqLen 50
-phyType Phy/WirelessPhy
-antType Antenna/OmniAntenna
-channelType Channel/WirelessChannel
-topoInstance $topo_instance
-wiredRouting ON or OFF
-mobileIP ON or OFF
-energyModel EnergyModel
-initialEnergy (in Joules)
-rxPower (in W)
-txPower (in W)
-agentTrace ON or OFF
-routerTrace ON or OFF
-macTrace ON or OFF
-movementTrace ON or OFF
-reset


Giá trị mặc định cho tất cả lựa chọn trên là rỗng trừ kiểu đánh địa chỉ,
-addressingType có giá trị mặc định là kiểu phẳng, lựa chọn -reset có thể được lựa
chọn để thiết lập lại tồn bộ tham số cấu hình nút mang giá trị mặc định của chúng.
Cấu hình nút cho nút khơng dây, di động chạy AODV như là giao thức định
tuyến adhoc trong cấu trúc mạng phân cấp được chỉ ra dưới đây, chúng ta quyết định
bật theo dõi chỉ ở mức tác tử và mức bộ định tuyến. Hơn nữa chúng ta giả sử rằng sơ
đồ kiến trúc mạng đã được tạo ra với lệnh "set topo [new Topography]". Lệnh cấu
hình nút như sau:
$ns_ node-config -addressingType hierarchical
-adhocRouting AODV
-llType LL
-macType Mac/802_11
-ifqType Queue/DropTail/PriQueue
-ifqLen 50
-antType Antenna/OmniAntenna
-propType Propagation/TwoRayGround
-phyType Phy/WirelessPhy
-topoInstance $topo
-channelType Channel/WirelessChannel
-agentTrace ON
-routerTrace ON
-macTrace OFF
-movementTrace OFF

Chú ý rằng lệnh cấu hình có thể ngắt thành những dòng riêng biệt như:
$ns_ node-config -addressingType hier
$ns_ node-config -macTrace ON

Các lựa chọn cần phải thay đổi chỉ thay đổi khi được gọi đến, ví dụ sau khi cấu
hình cho các nút di động AODV như trên, chúng ta có thể cấu hình cho các nút trạm

gốc AODV theo cách sau:
$ns_ node-config -wiredRouting ON

Trong khi tất cả các đặc tính khác của các nút trạm gốc và các nút di động là
giống nhau, các nút trạm gốc có khả năng định tuyến hữu tuyến, trong khi các nút di
động thì khơng có khả năng này. Trong trường hợp này chúng ta cần phải thay đổi cấu
hình nút chỉ khi nó là bắt buộc.
Tất cả các nút cụ thể được tạo ra sau lệnh cấu hình nút đã cho có cùng thuộc
tính trừ khi một phần hoặc tất cả lệnh cấu hình nút được thực hiện với các giá trị tham
số khác nhau. Nhưng sau khi tạo ra các nút di động và nút trạm gốc AODV, nếu chúng
ta muốn tạo ra các nút đơn, chúng ta sẽ sử dụng lệnh cấu hình nút sau:
Bài tiểu ḷn mơn học IP-Ứng dụng và bảo mật

24


Giới thiệu công cụ NS
$ns_ node-config -reset

Điều này sẽ thiết lập tất cả giá trị các tham số tới giá trị mặc định cơ bản được
định nghĩa khi cấu hình một nút đơn.
4.4 Bộ phân lớp

Chức năng của một nút khi nó nhận một gói là xem xét các trường của gói đó,
thơng thường là địa chỉ đích và một vài trường hợp là địa chỉ nguồn. Sau đó nó ánh xạ
các giá trị tới đối tượng giao diện ra của phía người nhận tiếp theo của gói tin này.
Trong ns, nhiệm vụ này được thực hiện bởi đối tượng classifier đơn, Các đối
tượng trong bộ đa phân lớp, xem xét việc phân chia cụ thể của việc chuyển gói tin qua
nút. Một nút trong ns sử dụng nhiều kiểu khác nhau của bộ phân lớp cho nhiều mục
đính khác nhau. Trong phần này xem xét một vài đối tượng phân lớp chung hơn, đơn

giản hơn trong ns.
Chúng ta bắt đầu mô tả lớp cơ sở trong phần này. Đoạn tiếp theo sẽ mô tả bộ
phân lớp địa chỉ (4.4.1), bộ phân lớp đa hướng (4.4.2), bộ phân lớp đa đường (4.4.3)
và cuối cùng bộ tái tạo (bản sao)(4.4.5)
Bộ phân lớp cung cấp cách đối xử với một gói tin dựa vào vài điều kiện logic
và lấy tham chiếu tới đối tượng mơ phỏng khác dựa trên kết quả tính tốn. Mỗi bộ
phân lớp gồm có một bảng các đối tượng mô phỏng được đánh chỉ mục bằng số khe
(slot number). Công việc của một bộ phân lớp là xác định số khe kết hợp với gói tin
nhận được và chuyển gói tin này tới đối tượng được tham chiếu bởi khe liên quan. Lớp
Classifier cung cấp một lớp cơ sở từ đó các bộ phân lớp khác được dẫn xuất từ lớp
này.
class Classifier : public NsObject {
public:
~Classifier();
void recv(Packet*, Handler* h = 0);
protected:
Classifier();
void install(int slot, NsObject*);
void clear(int slot);
virtual int command(int argc, const char*const* argv);
virtual int classify(Packet *const) = 0;
void alloc(int);
NsObject** slot_; /* table that maps slot number to a NsObject */
int nslot_;
int maxslot_;
};

Phương thức classify() là hoàn toàn ảo, chỉ định lớp Classifier được sử dụng
như một lớp gốc, phương thức alloc() cấp phát động không gian đủ cho bảng chứa số
cụ thể của các khe. Phương thức install() và clear() thêm vào hoặc xóa bỏ các đối

tượng từ bảng này. Phương thức recv() và giao diện OTcl là được thực thi như sau:
/*
* objects only ever see "packet" events, which come either
* from an incoming link or a local agent (i.e., packet source).
*/
void Classifier::recv(Packet* p, Handler*)
{
NsObject* node;
int cl = classify(p);

Bài tiểu luận môn học IP-Ứng dụng và bảo mật

25


×