Giáo trình Mạng máy tính (Bản đẹp)
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Mạng máy tính (Bản đẹp)", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Tài liệu đính kèm:
- giao_trinh_mang_may_tinh_ban_dep.pdf
Nội dung text: Giáo trình Mạng máy tính (Bản đẹp)
- Giáo trình: Mạng máy tính
- Chương 1 Các khái niệm căn bản về mạng và giao thức mạng 1. Mạng máy tính Mạng máy tính Là tập hợp các máy tính hoặc các thiết bị được nối với nhau bởi các đường truyền vật lý và theo một kiến trúc nào đó. Chúng ta có thể phân loại mạng theo qui mô của nó: Mạng LAN (Local Area Network)-mạng cục bộ: kết nối các nút trên một phạm vi giới hạn. Phạm vi này có thể là một công ty, hay một tòa nhà. Mạng WAN (Wide Area Network): nhiều mạng LAN kết nối với nhau tạo thành mạng WAN. MAN (Metropolitan Area Network), tương tự như WAN, nó cũng kết nối nhiều mạng LAN. Tuy nhiên, một mạng MAN có phạm vi là một thành phố hay một đô thị nhỏ. MAN sử dụng các mạng tốc độ cao để kết nối các mạng LAN của trường học, chính phủ, công ty, , bằng cách sử dụng các liên kết nhanh tới từng điểm như cáp quang. Khi nói đến các mạng máy tính, người ta thường đề cập tới mạng xương sống (backbone). Backbone là một mạng tốc độ cao kết nối các mạng có tốc độ thấp hơn. Một công ty sử dụng mạng backbone để kết nối các mạng LAN có tốc độ thấp hơn. Mạng backbone Internet được xây dựng bởi các mạng tốc độ cao kết nối các mạng tốc độ cao. Nhà cung cấp Internet hoặc kết nối trực tiếp với mạng backbone Internet, hoặc một nhà cung cấp lớn hơn. 1.1. Các đường kết nối trong mạng WAN Để kết nối tới một mạng WAN, có một số tùy chọn như sau: Khi một khách hàng cụ thể yêu cầu sử dụng mạng với thông lượng xác định, chúng ta có thể sử dụng các đường thuê bao (leased line). Các đường chuyển mạch (switched lines) được sử dụng bởi dịch vụ điện thoại thông thường. Một mạch được thiết lập giữa phía nhận và phát trong khoảng thời gian thực hiện cuộc gọi hoặc trao đổi dữ liệu. Khi không còn cần dùng đường truyền nữa, thì cần phải giải phóng đường truyền cho khách hàng khác sử dụng. Các ví dụ về các đường chuyển mạch là các đường POTS , ISDN, và DSL. Mạng chuyển mạch gói là mạng mà trong đó nhà cung cấp dịch vụ cung cấp công nghệ chuyển mạch để giao tiếp với mạng xương sống. Giải pháp này cung cấp hiệu năng cao và khả năng chia sẻ tài nguyên giữa các khách hàng. 1
- Các giao thức được sử dụng cho các mạng chuyển mạch bao gồm X.25 (64Kbps), Frame Relay (44.736Mbps), và ATM (9.953 Gbps). Kiến trúc mạng: Một trong những vấn đề cần quan tâm đối với một mạng máy tính là kiến trúc mạng. Nó cập tới hai khía cạnh là Hình trạng mạng và Giao thức mạng. Hình trạng mạng: Là cách nối các máy tính với nhau. Người ta phân loại mạng theo hình trạng mạng như mạng sao, mạng bus, mạng ring Giao thức mạng: Là tập hợp các qui tắc, qui ước truyền thông của mạng mà tất cả các thực thể tham gia truyền thông phải tuân theo. 1.2. Giao thức Ethernet Để có được sự hiểu biết tốt hơn về các mạng vật lý hoạt động như thế nào, chúng ta sẽ xem xét một số giao thức LAN phổ biến: giao thức Ethernet. Chín mươi phần trăm các thiết bị gắn với một mạng LAN sử dụng giao thức Ethernet, ban đầu được phát triển bởi Xerox, Digital Equipement, và Intel năm 1972. Ngày nay, Ethernet có thể hỗ trợ các đường truyền 100Mbps và 1Gbps. Rất nhiều công nghệ đường truyền có thể được sử dụng với một Ethernet. Người ta sử dụng một số qui ước để đặt tên giao thức Enternet. Tên này chỉ ra tốc độ của mạng Ethernet và các thuộc tính của công nghệ đường truyền. Các tên như vậy được bắt đầu bằng một số để chỉ ra tốc độ truyền tối đa, tiếp theo là một từ được sử dụng để xác định công nghệ truyền dẫn, và cuối cùng là một số để chỉ ra khoảng cách giữa hai nút. Ví dụ, 10Base2 ký hiệu một Ethernet hoạt động với tốc độ 10Mbps sử dụng kỹ thuật truyền trên băng tần cơ sở, với các cáp có chiều dài tối đa là 200m. Một số cấu hình thông dụng khác như sau: Chuẩn Tốc độ Kiểu cáp Mô tả Ethernet 10Base5 10Mbps Cáp đồng Đây là chuẩn ban đầu cho trục Ethernet 10BaseT 10Mbps Cáp đồng 10BaseT là một mạng 10Mbps với cáp xoắn. 100BaseTX 100Mbs Cáp đồng 100Mbps công nghệ cáp xoắn và khả năng truyền song công 1000BaseSX 1000Mbps Cáp đa chế 1000Mbps với cáp sợi quang. S độ :Short wavelength (850nm) 2
- Bảng 1.1 CSMA/CD (Carrier Sense Multiple Access/Collision Detect). Nhiều thiết bị được kết nối vào cùng một mạng và tất cả đều cùng có quyền truy xuất đồng thời. Khi một thông điệp được gửi đi, nó được truyền thông qua một mạng . Phía nhận được định danh bởi một địa chỉ duy nhất, và chỉ có nút này đọc thông điệp, còn các nút khác thì bỏ qua. Một vấn đề đặt ra là khi có nhiều nút cùng cố gắng gửi thông điệp tại cùng một thời điểm, điều này có thể phá hỏng các gói tin. Giải pháp cho vấn đề này là mỗi nút mạng giám sát mạng và có thể phát hiện mạng đang rảnh hay bận. Một nút chỉ có thể bắt đầu gửi dữ liệu khi không có dữ liệu nào được gửi đi trên mạng trước đó. CSMA là một bộ phận của CSMA/CD. Tuy nhiên vẫn có khả năng là hai nút, sau khi kiểm tra thấy mạng không bận, bắt đầu gửi gói tin cùng một thời điểm trên cùng cáp mạng. Điều này có thể gây lên xung đột giữa hai gói tin, kết quả là phá hỏng dữ liệu. Cả hai phía gửi đều nhận thức được gói tin bị hỏng bởi vì nó vẫn lắng nghe mạng khi gửi dữ liệu, và vì thế có thể phát hiện xung đột. Đây là CD (Collision Dection) trong CSMA/CD. Cả hai nút dừng việc truyền dữ liệu ngay tức thời, và chờ một thời điểm nhất định trước khi kiểm tra mạng trở lại để xem mạng có rỗi hay không và truyền lại. Mỗi nút trên mạng sử dụng một địa chỉ MAC (Media Access Control) để định danh duy nhất. Địa chỉ này được định nghĩa bởi thiết bị giao tiếp mạng. Một gói tin được gửi đi trên mạng, nhưng nếu thiết bị mạng không nhận diện host của nó như một host nhận, nó sẽ bỏ qua gói tin và chuyển tiếp nó. Các giao thức khác IBM đã phát triển giao thức Token Ring (IEEE802.5), trong đó các nút mạng được kết nối theo một vòng. Với Ethernet, bất kỳ một nút nào cũng có thể gửi một thông điệp khi không có gói tin nào trên mạng. Với Token Ring mỗi nút có một quyền truy xuất tới mạng theo một thứ tự định trước. Một token lưu chuyển vòng quanh vòng, và chỉ nút lệnh nào có thẻ bài mới có thể gửi thông điệp. Ngày nay, Ethernet đang thay thế dần các mạng Token Ring bởi vì các mạng này tốn kém và khó cài đặt. AppleTalk là một giao thức mạng LAN được phát triển bởi Apple tương đối phổ biến trong các trường học, các nhà máy, 3
- ATM là một giao thức khác có thể tìm thấy trong mạng LAN. Nó hỗ trợ các mạng tốc độ cao sử dụng kỹ thuật chuyển mạch và có đảm bảo chất lượng dịch vụ. 1.3. Các thành phần vật lý Một vấn đề quan trọng để biết về mạng là biết về phần cứng. Chúng ta sẽ xem xét các thành phần chủ yếu của một mạng LAN sau: o Thiết bị giao tiếp mạng o Hub o Switch o Router Thiết bị giao tiếp mạng (Network Interface Thiết bị) NIC là thiết bị giao tiếp được sử dụng để kết nối một thiết bị với mạng LAN. Nó cho phép chúng ta gửi và nhận các thông điệp từ mạng. Một NIC có một địa chỉ MAC duy nhất mà cung cấp định danh duy nhất cho từng thiết bị. Địa chỉ MAC là một số 12 byte-hệ 16 được gán cho thiết bị mạng. Địa chỉ này có thể được thay đổi bởi một trình điều khiển mạng một cách linh hoạt (như trong trường hợp của hệ thống DECnet, mạng được phát triển bởi Digital Equipment), nhưng thông thường địa chỉ MAC không thay đổi. Ta có thể tìm địa chỉ MAC của một máy sử dụng hệ điều hành Windows bằng cách dùng tiện ích dòng lệnh ipconfig trong DOS với tham số switch Hình 1.1 Hub 4
- Nhiều thiết bị có thể được kết nối một cách dễ dàng với sự giúp đỡ của một hub. Hub là một thiết bị kết nối gắn nhiều thiết bị vào LAN. Mỗi thiết bị thường kết nối thông qua một cáp tới một cổng trên hub. Hub hoạt động như một bộ chuyển tiếp. Khi nó chuyển từng thông điệp từ cổng này tới cổng khác, và chuyển tới mạng. Hub là một thành phần tương đối đơn giản của một mạng, hoạt động ở tầng vật lý để truyền dữ liệu mà không cần thao tác xử lý nào. Điều này làm cho các hub dễ cài đặt và quản lý, vì chúng không đòi hỏi cấu hình đặc biệt nào. Switch Các chuyển mạch (switch) phân chia mạng thành các đoạn (segment). So với hub, switch là một thiết bị thông minh hơn nhiều. Switch lưu trữ các địa chỉ MAC của các thiết bị được kết nối tới các cổng của nó trong bảng lookup. Các bảng lookup cho phép switch lọc các thông điệp mạng và không giống với hub, nó không chuyển tiếp các thông điệp tới từng cổng. Điều này loại bỏ các xung đột có thể xảy ra và mạng có thể đạt được hiệu năng tốt hơn. Chức năng chuyển mạch được thực hiện bằng cách sử dụng phần cứng. Router Router là một thiết bị trung gian mạng, kết nối nhiều mạng vật lý. Một mạng có nhiều host có thể được phân chia thành các phần riêng, hay còn gọi là subnet. Ưu điểm của các subnet là: a. Hiệu năng được cải thiện bằng cách giảm broadcast, broadcast là 1 thông điệp được gửi tới tất cả các nút của mạng. b. Khả năng hạn chế người dùng trong từng mạng con xác định đưa ra những ưu điểm về bảo mật. c. Các subnet nhỏ hơn sẽ dễ quản lý hơn so với một mạng lớn. Các router không chỉ được sử dụng trong LAN, chúng có một vai trò quan trọng trong WAN. Router nhận một thông điệp và chuyển tiếp nó tới đích bằng cách sử dụng đường đi tốt nhất tới đích đó. Một Router lưu giữ một bảng định tuyến liệt kê tất cả các cách mà các mạng có thể đạt tới. Thông thường sẽ có một số đường đi từ mạng này tới mạng khác, nhưng chỉ có một trong số đó là tốt nhất, và nó là con đường được mô tả trong bảng định tuyến. Các router truyền tin bằng cách sử dụng các giao thức định tuyến để phát hiện các router khác trên mạng, và hỗ trợ cho việc trao đổi thông tin về các mạng được gắn với từng bộ định tuyến. Thông tin mà một bộ định tuyến thu thập về các đường đi giữa các mạng được gọi là độ đo router, và có thể bao gồm những thông tin như sự mất mát gói tin và thời gian truyền tin. Thông tin được sử dụng để tạo ra độ đo tùy thuộc vào giao thức định tuyến: 5
- d. Giao thức định tuyến vectơ khoảng cách e. Các giao thức RIP(Routing Information Protocol) và IGRP(Interior Gateway Routing Protocol) sử dụng một biến đếm để chỉ ra số router mà gói tin phải đi qua để đến đích. Các giao thức này thường lựa chọn các đường đi với ít router, mà không quan tâm đến tốc độ và độ tin cậy. f. Các giao thức định tuyến trạng thái liên kết g. Việc tính toán đường đi tốt nhất của các giao thức định tuyến OSPF và BGP quan tâm đến nhiều yếu tố như tốc độ, độ tin cậy, và thậm chí là chi phí của đường đi. h. Các giao thức định tuyến lai i. Các giao thức này sử dụng sự kết hợp việc tính toán trạng thái liên kết và vectơ khoảng cách. Vấn đề tìm đường đi Với cấu hình TCP/IP, một gateway mặc định được thiết lập. Đây là một địa chỉ IP của cổng bộ định tuyến mà subnet kết nối tới. Bộ định tuyến này được sử dụng khi một host ở bên ngoài subnet cần được liên lạc. Ta có thể thấy bảng định tuyến cục bộ trên hệ điều hành Windows bằng cách sử dụng lệnh ROUTE PRINT trên dòng lệnh Lệnh này hiển thị các gateway sẽ được sử dụng cho mỗi liên kết mạng. Hình 1.2 Một lệnh hữu ích khác là lệnh TRACERT. Lệnh này cho phép chúng ta kiểm tra đường đi được sử dụng để đi tới đích. 6
- Hình 1.3 2. Mô hình phân tầng ISO đã định nghĩa một mô hình cho một mạng đã được chuẩn hóa sẽ thay thế cho TCP/IP,DECNet và các giao thức khác như là một giao thức mạng cơ bản được sử dụng cho Internet. Tuy nhiên, do sự phức tạp của OSI, mô hình này không được cài đặt và sử dụng nhiều trong thực tế. TCP/IP đơn giản hơn nhiều và vì vậy có thể tìm thấy ở nhiều nơi. Nhưng có rất nhiều ý tưởng mới từ giao thức OSI có thể tìm thấy trong phiên bản tiếp theo của IP, IPv6. Trong khi giao thức OSI không được xây dựng đầy đủ trong thực tế, nhưng mô hình bảy tầng đã rất thành công và nó hiện đang được sử dụng như là một mô hình tham chiếu để mô tả các giao thức mạng khác nhau và chức năng của chúng. Các tầng của mô hình OSI phân chia các nhiệm vụ cơ bản mà các giao thức mạng phải thực hiện, và mô tả các ứng dụng mạng có thể truyền tin như thế nào. Mỗi tầng có một mục đích cụ thể và được kết nối với các tầng ở ngay dưới và trên nó. Bảy tầng của mô hình OSI. 7
- Hình 1.4 Tầng ứng dụng (Application): định nghĩa một giao diện lập trình giao tiếp với mạng cho các ứng dụng người dùng. Tầng trình diễn (Presentation): có trách nhiệm mã hóa dữ liệu từ tầng ứng dụng để truyền đi trên mạng và ngược lại. Tầng phiên (Session): tạo ra một liên kết ảo giữa các ứng dụng. Tầng giao vận (Transport): cho phép truyền dữ liệu với độ tin cậy cao. Tầng mạng (Network): cho phép truy xuất tới các nút trong mạng LAN bằng cách sử dụng địa chỉ logic Tâng liên kết dữ liệu (Data Link): truy xuất tới một mạng vật lý bằng các địa chỉ vật lý. Cuối cùng, tầng vật lý (Physical): có thể bao gồm các thiết bị kết nối, cáp nối. Bây giờ chúng ta tìm hiểu khái niệm của các tầng này bằng cách xem xét chức năng của từng tầng chi tiết hơn. 2.1. Tầng 1:Tầng vật lý Tầng vật lý bao gồm môi trường vật lý như yêu cầu về cáp nối, các thiết bị kết nối, các đặc tả giao tiếp, hub và các repeater, 2.2. Tầng 2: Tầng liên kết dữ liệu Địa chỉ MAC mà chúng ta đã đề cập là địa chỉ của tầng 2. Các nút trên LAN gửi thông điệp cho nhau bằng cách sử dụng các địa chỉ IP, và các địa chỉ này phải được chuyển đổi sang các địa MAC tương ứng. 8
- Giao thức phân giải địa chỉ (ARP: Address Resolution Protocol) chuyển đổi địa chỉ IP thành địa chỉ MAC.Một vùng nhớ cache lưu trữ các địa chỉ MAC tăng tốc độ xử lý này, và có thể kiểm tra bằng tiện ích arp -a, 2.3. Tầng 3: Tầng mạng Tầng mạng là tầng nằm phía trên tầng liên kết. Trong tầng 3, địa chỉ logic được sử dụng để kết nối tới các nút khác. Các địa chỉ MAC của tầng 2 chỉ có thể được sử dụng trong một mạng LAN, và chúng ta phải sử dụng cách đánh địa chỉ của tầng 3 khi truy xuất tới các nút trong mạng WAN. Internet Protocol là giao thức tầng 3; nó sử dụng các địa chỉ IP để định danh các nút trên mạng. Các router ở tầng 3 được sử dụng để định đường đi trong mạng. 2.4.Tầng 4:Tầng giao vận Tầng mạng định danh các host bởi các địa chỉ logic. Tầng ứng dụng nhận biết một ứng dụng thông qua cái gọi là điểm cuối (endpoint). Với giao thức TCP, endpoint được nhận biết bởi một số hiệu cổng và địa chỉ IP. Tầng giao vận được phân loại theo cách truyền tin với độ tin cậy hay không. Truyền tin với độ tin cậy là khi có một lỗi được tạo ra nếu thông điệp được gửi đi nhưng không nhận được một cách đúng đắn. Trong khi truyền tin có độ tin cậy không cao sẽ không kiểm tra xem liệu thông điệp được gửi đi đã nhận được hay chưa. Trong truyền tin với độ tin cậy, tầng giao vận có nhiệm vụ gửi đi các gói tin xác thực hay các thông điệp truyền lại nếu dữ liệu bị hỏng hay bị thất lạc, hay dữ liệu bị trùng lặp. Một cách khác để phân loại các mạng truyền tin là phân loại mạng theo hướng liên kết hay phi liên kết Với truyền tin hướng liên kết, một liên kết phải được thiết lập trước khi các thông điệp được gửi hoặc được nhận. Với truyền tin phi liên kết thì không cần giai đoạn thiết lập liên kết. 2.5. Tầng 5: Tầng phiên Với mô hình OSI, tầng phiên xác định cá dịch vụ cho một ứng dụng, như đăng nhập và đăng xuất một ứng dụng. Tầng phiên biểu diễn một liên kết ảo giữa các ứng dụng. Liên kết tầng phiên độc lập với liên kết vật lý ở tầng giao vận, và các liên kết tầng giao vận được yêu cầu cho một liên kết ở tầng phiên. 2.6.Tầng 6:Tầng trình diễn Tầng trình diễn được sử dụng để định dạng dữ liệu theo các yêu cầu của ứng dụng. Mã hóa, giải mã, và nén dữ liệu thường diễn ra ở tầng này. 2.7. Tầng 7:Tầng ứng dụng 9
- Tầng ứng dụng là tầng cao nhất của mô hình OSI. Tầng này bao gồm các ứng dụng sử dụng các tiện ích mạng. Các ứng dụng này có thể thực hiện các tác vụ như truyền tệp tin, in ấn, e-mail, duyệt web, 3. Các giao thức mạng Các tầng OSI định nghĩa một mô hình các tầng giao thức, và cách mà chúng hoạt động cùng với nhau. Chúng ta so sánh các tầng OSI với một cài đặt cụ thể:. Chồng giao thức TCP/IP là một dạng cụ thể của mô hình OSI, nó bao gồm 4 tầng. Giao thức IP tương ứng với tầng 3 của mô hình OSI; TCP và UDP tương ứng với tầng 4 của mô hình OSI, và chúng thực hiện các nhiệm vụ của tầng phiên, tầng trình diễn, và tầng ứng dụng Trong mục tiếp theo, chúng ta sẽ xem xét chức năng và mục đích của các giao thức của họ giao thức TCP/IP theo trình tự sau: Các giao thức cơ bản Các giao thức Internet Các giao thức E-mail Các giao thức khác 3.1. Các giao thức cơ bản Như chúng ta có thể thấy, họ giao thức TCP/IP có cấu trúc phân tầng đơn giản hơn nhiều so với mô hình 7 tầng của mô hình OSI. TCP và UDP là các giao thức tầng giao vận tương ứng với tầng 4 của mô hình 7 tầng OSI. Cả hai giao thức này đều sử dụng giao thức IP, một giao thức tương ứng với tầng 3 của mô hình OSI (tầng mạng). Cũng như ba giao thức này có hai giao thức cơ bản trong họ giao thức TCP/IP mở rộng tính năng của giao thức IP: ICMP và IGMP. 3.1.1. IP-Internet Protocol Giao thức Internet kết nối hai nút. Mỗi nút được định danh bởi một địa chỉ IP 32bit, được gọi là địa chỉ IP của host. Khi gửi một thông điệp, giao thức IP nhận thông điệp từ các giao thức tầng trên như TCP hay UDP và đưa vào trường header chứa thông tin của host đích. Cách tốt nhất để hiểu giao thức IP là bằng cách xem các trường thông tin header IP chi tiết. Thông tin này được liệt kê trong bảng sau. Trường Độ dài Mô tả IP Version 4 bits Phiên bản IP. ( Phiên bản giao thức hiện nay (Phiên bản IP) là IPv4) IP Header Length 4 bits Chiều dài của header. (Chiều dài Header) Type of Service 1 byte Kiểu dịch vụ cho phép một thông điệp được (Kiểu dịch vụ) đặt ở chế độ thông lượng cao hay bình 10
- thường, thời gian trễ là bình thường hay lâu, độ tin cậy bình thường hay cao. Điều này có lợi cho các gói được gửi đi trên mạng. Một số kiểu mạng sử dụng thông tin này để xác định độ ưu tiên Total Length 2 bytes Hai byte xác định tổng chiều dài của thông (Tổng chiều dài) điệp-header và dữ liệu. Kích thước tối đa của một gói tin IP là 65,535, nhưng điều này là không thực tế đối với các mạng hiện nay. Kích thước lớn nhất được chấp nhận bởi các host là 576 bytes. Các thông điệp lớn có thể phân thành các đoạn-quá trình này được gọi là quá trình phân đoạn Identification 2 bytes Nếu thông điệp được phân đoạn, trường (Định danh) định danh trợ giúp cho việc lắp ráp các đoạn thành một thông điệp. Nếu một thông điệp được phân thành nhiều đoạn, tất cả các đoạn của một thông điệp có cùng một số định danh. Flags 3 bits Các cờ này chỉ ra rằng thông điệp có được phân đoạn hay không, và liệu gói tin hiện thời có phải là đoạn cuối cùng của thông điệp hay không. Fragment Offset 13 bits 13 bit này xác định offset của một thông điệp. Các đoạn có thể đến theo một thứ tự khác với khi gửi, vì vậy trường offset là cần thiết để xây dựng lại dữ liệu ban đầu. Đoạn đầu tiên của một thông điệp có offset là 0 Time to Live 1 byte Xác định số giây mà một thông điệp tồn tại trước khi nó bị loại bỏ. Protocol 1 byte Byte này chỉ ra giao thức được sử dụng ở mức tiếp theo cho thông điệp này. Các số giao th ức Header Checksum 2 bytes Đây là chỉ là checksum của header. Bởi vì header thay đổi với từng thông điệp mà nó chuyển tới, checksum cũng thay đổi. Source Address 4 bytes Cho biết địa chỉ IP 32 bit của phía gửi Destination 4 bytes Địa chỉ IP 32 bit của phía nhận Address Options variable Padding variabe Bảng 1.2 11
- Các địa chỉ IP Mỗi nút trên mạng TCP/IP có thể được định danh bởi một địa chỉ IP 32- bit. Thông thường một địa chỉ IP được biểu diễn bởi bộ bốn x.x.x.x, chẳng hạn 192.168.0.1 . Mỗi số trong bốn số này biểu diễn một byte của địa chỉ IP. Một địa chỉ IP gồm hai phần: phần mạng và phần host. Tùy thuộc vào lớp mạng, phần mạng bao gồm một, hoặc hai hoặc ba byte đầu tiên. Lớp Byte 1 Byte 2 Byte 3 Byte 4 A Networks (1-126) Host (0-255) Host (0-255) Host (0- 255) B Networks (128- Networks (0- Host (0-255) Host (0- 191) 255) 255) C Networks (192- Networks (0- Networks (0- Host (0- 223) 255) 255) 255) Bảng 1.3 Bit đầu tiên của địa chỉ mạng lớp A là 0,vì vậy byte đầu tiên của địa chỉ lớp A nằm trong dải từ 00000001 (1) đến 01111110 (126). Ba byte còn lại phục vụ cho việc định danh các nút trên mạng, cho phép ta kết nối hơn 16 triệu thiết bị vào mạng lớp A. Chú ý rằng các mạng trong bảng trên không đề cập tới các địa chỉ có byte đầu là 127-đây là khoảng địa chỉ dự phòng. Địa chỉ 127.0.0.1 là địa chỉ của localhost, và địa chỉ 127.0.0.0 là địa chỉ loopback. Các địa chỉ IP của các mạng thuộc lớp B luôn luôn có hai bit đầu tiên của byte đầu là 10, đưa ra khoảng địa chỉ là 10000000 (128) đên 10111111 (191). Byte thứ hai dùng để định danh mạng có giá trị từ 0 đến 255, hai byte còn lại để định danh các nút trên một mạng; tổng cộng là 65534 thiết bị. Các địa chỉ IP của các mạng thuộc lớp C luôn luôn có ba bit đầu tiên của byte đầu là 110, khoảng giá trị của byte đầu là từ 11000000 (192) đến 11011111 (223). Mạng này chỉ có một byte được thiết lập để định danh host, vì vậy chỉ có 254 thiết bị được kết nối vào mạng lớp C. Các địa chỉ IP riêng Để tránh cạn kiệt các địa chỉ IP, các host không được kết nối trực tiếp với Internet có thể sử dụng một địa chỉ trong các khoảng địa chỉ riêng. Các địa chỉ IP riêng không duy nhất về tổng thể, mà chỉ duy nhất về mặt cục bộ trong phạm vi mạng đó. Tất cả các lớp mạng dự trữ các khoảng nhất định để sử dụng như là các địa chỉ riêng cho các host không cần truy cập trực tiếp tới Internet. Các host như vậy vẫn có thể truy cập Internet thông qua một gateway mà không cần chuyển tiếp các địa chỉ IP riêng. 12
- Lớp Khoảng địa chỉ riêng A 10 B 172.16-172.31 C 192.168.0- 192.168.255 Bảng 1.4 Các subnet Việc kết nối hai nút của hai mạng khác nhau cần có một router. Định danh host của mạng lớp A cần có 24 bit; trong khi mạng lớp C, chỉ có 8 bit. Router phân chia định danh host thành hai phần một phần được gọi là subnet và phần còn lại là phần host 3.1.2. IPv6 Tiền thân của giao thức IP được phát triển bởi Bộ Quốc Phòng Mỹ năm 1960 và cho tới năm 1980 họ giao thức TCP/IP mới ra đời. Bởi IP được xây dựng dựa trên các giao thức mạng DARPA hiện có, nó trở thành phiên bản 4, gọi là IPv4. Lúc đó ý tưởng về các máy di động chưa được kết nối vào Internet nên số host được hỗ trợ bởi IP là tạm đủ. Nhưng hiện nay có rất nhiều thiết bị được kết nối vào Internet, nhu cầu về số địa chỉ IP tăng cao. Một phiên bản mới của địa chỉ IP được phát triển bởi IETF: IPv6. Sự thay đổi quan trọng nhất so với IPv4 là việc sử dụng 128bit để đánh địa chỉ các nút chứ không phải là 32bit nữa. 3.1.3. -Số hiệu cổng Giao thức IP sử dụng các địa chỉ IP để định danh các nút trên mạng, trong khi tầng giao vận sử dụng các điểm cuối (endpoint) để định danh các ứng dụng. Các giao thức TCP và UDP sử dụng một số hiệu cổng cùng với một địa chỉ IP để xác định điểm cuối của một ứng dụng. Các số hiệu cổng của TCP và UDP được phân thành ba loại Các số hiệu cổng hệ thống Các số hiệu cổng người dùng Các số hiệu cổng riêng và động Các số hiệu cổng hệ thống nằm trong khoảng từ 0 đến 1023. Các cổng hệ thống chỉ được sử dụng bởi các tiến trình được quyền ưu tiên của hệ thống. Các giao thức nổi tiếng có các số hiệu cổng nằm trong khoảng này. Các số hiệu cổng người dùng nằm trong khoảng từ 1024 đến 49151. Các ứng dụng server của bạn sẽ nhận một trong các số này làm cổng, hoặc bạn có thể đăng ký số hiệu cổng với IANA . Các cổng động nằm trong khoảng từ 49152 đến 65535. Khi không cần thiết phải biết số hiệu cổng trước khi khởi động một ứng dụng, một số hiệu cổng trong khoảng này sẽ là thích hợp. Các ứng dụng client kết nối tới server có thể sử dụng một cổng như vậy. 13
- Nếu chúng ta sử dụng tiện ích netstat với tùy chọn –a, chúng ta sẽ thấy một danh sách tất cả các cổng hiện đang được sử dụng, nó cũng chỉ ra trạng thái của liên kết-nó đang nằm trong trạng thái lắng nghe hay liên kết đã được thiết lập. Hình 1.5 3.1.4. TCP (Transmission Control Protocol) Giao thức TCP là giao thức truyền tin hướng liên kết có thể sử dụng truyền tin với độ tin cậy cao. Trong đó giao thức tầng 4 có thể gửi các xác thực rằng đã nhận dữ liệu và yêu cầu truyền lại dữ liệu nếu chưa nhận được dữ liệu hoặc dữ liệu bị hỏng. Các trường header được liệt kê trong bảng sau: Trường Độ Mô tả dài Cổng nguồn 2 Số hiệu cổng của nguồn (source port) bytes Cổng đích 2 Số hiệu cổng đích (destination port) bytes Số thứ tự 4 Số thứ tự được tạo ra bởi nguồn và được sử (Sequence bytes dụng bởi đích để sắp xếp lại các gói tin để tạo Number) ra thông điệp ban đầu, và gửi xác thực tới nguồn. Acknowledge 4 Number bytes Data offset 4 Các chi tiết về nơi dữ liệu gói tin bắt đầu bits Reserved 6 bit Dự phòng Control 14
- Window Size 2 Trường này chỉ ra kích thước của vùng đệm bytes nhận. Phía nhận có thể thông báo cho phía gửi kích thước dữ liệu tối đa mà có thể được gửi đi bằng cách sử dụng các thông điệp xác thực Checksum 2 Checksum cho header và dữ liệu để xác định bytes xem gói tin có bị hỏng không Urgent Pointer 2 Trường này thông báo cho phía nhận biết có dữ bytes liệu khẩn Options Padding Bảng 1.5 Giao thức TCP là một giao thức phức tạp và mất thời gian do cơ chế bắt tay, nhưng giao thức này đảm bảo các gói tin đến đúng đích. Một số giao thức ứng dụng sử dụng TCP như HTTP, FTP, SMTP, và Telnet. TCP yêu cầu một liên kết phải được thiết lập trước khi dữ liệu được gửi đi. Ứng dụng server phải thực hiện một thao tác mở thụ động để tạo một liên kết với một số hiệu cổng cho trước. 3.1.5. UDP-User Datagram Protocol Ngược với giao thức TCP, UDP là một giao thức có tốc độ truyền tin nhanh vì nó chỉ xác định cơ chế tối thiểu để truyền dữ liệu. Tất nhiên điều này có một số nhược điểm. Các thông điệp có thể được nhận theo bất kỳ thứ tự nào. Thông điệp được gửi đầu tiên có thể được nhận sau cùng. Không có gì đảm bảo là các gói tin sẽ đến đích, và các thông điệp có thể bị thất lạc, hoặc thậm chí có thể nhận được hai bản sao của cùng một thông điệp. UDP không cần giai đoạn thiết lập liên kết, dữ liệu được gửi đi ngay khi cần. UDP không gửi các thông điệp xác thực, vì vậy dữ liệu có thể nhận được hoặc bị thất lạc. Nếu cần truyền dữ liệu có độ tin cậy nó phải được thực hiện trong một giao thức mức cao hơn. Vậy đâu là ưu điểm của giao thức UDP, tại sao chúng ta lại cần sử dụng một giao thức có độ tin cậy thấp như vậy? Để hiểu được lý do tại sao ta lại phải sử dụng giao thức UDP ta cần phân biệt giữa truyền unicast, broadcast và multicast. Một thông điệp unicast được gửi từ nút này tới nút khác. Kiểu truyền tin là truyền tin điểm-điểm. Giao thức TCP chỉ hỗ trợ truyền tin unicast. Nếu một server muốn truyền tin với nhiều client bằng cách sử dụng giao thức UDP, mỗi client phải thiết lập một liên kết, vì các thông điệp chỉ có thể gửi tới một nút. Truyền tin broadcast nghĩa là một thông điệp có thể được gửi tới tất cả các nút trong một mạng. Multicast cho phép các thông điệp được truyền tới một nhóm các nút được lựa chọn. UDP có thể được sử dụng cho truyền tin unicast nếu cần tới tốc độ truyền tin nhanh, như truyền tin đa phương tiện, nhưng ưu điểm chính của 15
- UDP là truyền tin broadcast và truyền tin multicast. Thông thường chúng ta không muốn tất cả các nút gửi về các xác thực cho server vì như vậy sẽ làm cho server quá tải. Header UDP ngắn và đơn giản hơn rất nhiều so với TCP Trường thông tin Độ dài Mô tả Source port (Cổng 2 byte Xác định cổng nguồn là một tùy chọn với nguồn) UDP. Nếu trường này được sử dụng, phía nhận thông điệp có thể gửi một phúc đáp tới cổng này Destination Port 2 byte Số hiệu cổng đích Length 2 byte Chiều dài của thông điệp bao gồm header và dữ liệu Checksum 2 byte Để kiểm tra tính đúng đắn Bảng 1.5 3.1.6. ICMP-Internet Control Message Protocol ICMP là một giao thức được phát triển từ giao thức IP, điểm khác biệt của ICMP so với giao thức IP là các thông tin phản hồi về trạng thái của hệ thống được ICMP phản hồi bởi các thông điệp. Các lỗi được phát hiện có thể được thông báo bằng các thông điệp ICMP. Các thông điệp ICMP được sử dụng để gửi các thông tin phản hồi về tình trạng của mạng. Ví dụ, một router gửi thông điệp ICMP “destination unreachable” nếu không tìm thấy một điểm vào cho mạng trong bảng định tuyến. Một router cũng có thể gửi thông điệp ICMP “redirect” nếu tìm thấy đường đi tốt hơn. ICMP không có trên giao thức IP mà được gửi đi trong các header IP. Trường thông tin Độ Mô tả dài Type 1 Trường này xác định kiểu thông điệp ICMP. Ví byte dụ, type có giá trị 3 nghĩa là không đến được đích, 11 nghĩa là quá thời gian, và 12 nghĩa là các tham số header không đúng Code 1 Code cung cấp thông tin về kiểu thông điệp. Nếu byte kiểu type là 3, “destination unreachable”, thì code xác định là mạng (0), host (1), hay protocol (2), hoặc port (3) là không thể đến được Checksum 2 Checksum của thông điệp ICMP byte 4 Bốn byte cuối cùng của header ICMP có thể cung byte cấp thông tin bổ trợ tùy thuộc vào kiểu thông điệp Header IP thông thường 16
- Bảng 1.6 Một số kiểu có thể được gửi bằng cách sử dụng các thông điệp ICMP: o Echo, Echo Reply o Lệnh ping gửi lệnh ICMP tới thiết bị đích, xem thiết bị hoạt động tốt hay không và có kết quả trả lời lại. o Destination unreachable (Không đến được đích), Redirect Một router trả về thông điệp ICMP “destination unreachable” nếu không thể liên lạc được với thiết bị đích, hoặc “redirect” (định hướng lại) nếu tìm thấy một đường đi tốt hơn tới đích. o TTL (Time To Live):Vượt quá thời gian cho phép Lệnh Ping Tiện ích dòng lệnh ping gửi một thông điệp ICMP tới thiết bị đích được xác định bởi hostname và địa chỉ IP trong lệnh ping. Nếu thiết bị là đến được thì ICMP Echo Reply được gửi trở lại. Lệnh này rất hữu ích khi muốn kiểm tra xem có liên lạc được với thiết bị hay không, hay là có các vấn đề lỗi trung gian Hình 1.6 3.1.7. IGMP-Internet Group Management Protocol Tương tự với ICMP, IGMP là sự mở rộng của giao thức IP và phải được cài đặt trong module IP. IGMP được sử dụng bởi các ứng dụng multicast. Khi gửi các thông điệp broadcast tới một LAN, mỗi nút trong LAN phân tích thông điệp và gửi lên cho tầng giao vận để kiểm tra xem có ứng dụng nào muốn nhận các thông điệp từ cổng broadcast. Nếu không ứng dụng nào lắng nghe, thông điệp bị phá hủy và không vượt qua được tầng giao vận. Điều này nghĩa là mỗi host cần một số chu kỳ của CPU cho dù thông điệp broadcast có cần hay không. 17
- Multicast giải quyết vấn đề này, bằng cách gửi các thông điệp tới một nhóm các nút chứ không phải là tất cả các nút trong LAN. Thiết bị giao tiếp mạng có thể phát hiện xem hệ thống có cần quan tâm đến thông điệp hay không bằng cách phân tích địa chỉ broadcast mà không cần sự trợ giúp của CPU. 3.2. Các giao thức Internet 3.2.1. Giao thức truyền tệp tin –FTP (File Transfer Protocol) FTP được sử dụng để tải các tệp lên server, và tải về các tệp từ server. Nó là một giao thức mức ứng dụng, dựa trên nền tảng của giao thức TCP. Ứng dụng client cung cấp một giao diện người dùng và tạo ra một yêu cầu FTP tương ứng với yêu cầu của người dùng cùng với đặc tả của FTP. Lệnh FTP được gửi tới ứng dụng server thông qua giao thức TCP/IP, trình thông dịch trên FTP phải thông dịch lệnh FTP tương ứng. Tùy thuộc vào lệnh FTP, một danh sách các tệp hoặc một tệp từ hệ thống tệp của server được trả về cho client trong đáp ứng của FTP. Giao thức FTP có các đặc trưng sau: Truyền dữ liệu với độ tin cậy cao thông qua giao thức TCP Cho phép truy xuất vô danh hoặc xác thực người dùng với username và password Các tệp tin được truyền đi dưới dạng mã ASCII hoặc dữ liệu nhị phân Các lệnh FTP có thể được nhóm thành các loại sau: Các lệnh điều khiển việc truy xuất Các lệnh điều khiển việc truy nhập xác định tên người dùng và mật khẩu, các chế độ thiết lập có thể được thiết lập lại (REIN), và liên kết có thể được kết thúc (QUIT). Các lệnh truyền tham số Truyền FTP có thể được cấu hình với các lệnh tham số truyền. Thay đổi việc truyền dữ liệu từ ASCII thành nhị phân, nén dữ liệu, thay đổi các cổng để gửi dữ liệu được hỗ trợ bởi các lệnh này. Các lệnh dịch vụ FTP Sao chép các tệp tin từ server (RETR), sao chép các tệp tin lên server (STOR), xóa các tệp (DELE), thay đổi các tên tệp tin (RNTO), tạo các thư mục (MKD), và yêu cầu liệt kê một danh sách các tệp. FTP Client Cách tốt nhất để làm quen với giao thức FTP là bằng cách sử dụng tiện ích ftp như dưới đây. Chương trình ftp hoạt động thông qua dấu nhắc lệnh ftp> cho phép chúng ta nhập vào các lệnh. Các lệnh này khác với các lệnh của giao thức FTP-ta có thể thấy được chúng bằng cách nhập vào ?. Dưới đây, ta sẽ nhập vào lệnh open ftp.microsoft.com để tạo ra một liên kết tới host 18
- ftp.microsoft.com. Nhập vào username là anonymous. Đáp ứng 230 chỉ ra liên kết đã được thiết lập. Hình 1.7 Một client FTP khác có trong trình duyệt Microsoft Internet Explorer 19
- Hình 1.8 3.2.2. HTTP-Giao thức truyền siêu văn bản (Hypertext Transfer Protocol) HTTP là một giao thức được sử dụng bởi các ứng dụng web. HTTP là một giao thức có độ tin cậy cao, được cài đặt dựa trên nền giao thức TCP. Tương tự như FTP, HTTP cũng được sử dụng để truyền các tệp tin qua mạng. Tuy nhiên, không giống với FTP, nó có các đặc trưng như đệm dữ liệu, định danh các ứng dụng client, hỗ trợ cho các định dạng kèm theo khác, như MIME, Những đặc trưng này có trong header HTTP. 3.2.3. HTTPS-HTTP over SSL (Secure Socket Layer) Nếu có yêu cầu trao đổi dữ liệu mật với một webserver, người ta sử dụng giao thức HTTPS. HTTPS là một sự mở rộng của giao thức HTTP và các nguyên tắc đã được thảo luận ở mục trước vẫn được áp dụng ở đây. Tuy nhiên cơ chế thì hoàn toàn khác, HTTPS sử dụng lớp Socket bảo mật SSL(Secure Socket Layer) được phát triển bởi Netscape. SSL ở tầng trên của giao thức TCP và bảo mật thông tin được truyềntrên mạng bằng cách sử dụng nguyên tắc mã hóa công khai. 3.3. Các giao thức E-mail Có một số giao thức sử dụng cho e-mail phổ biến như sau SMTP-Simple Mail Transfer Protocol SMTP là một giao thức để gửi và nhận các e-mail. Nó có thể được sử dụng để gửi e-mail giữa client và server sử dụng cùng giao thức giao vận, hoặc để gửi e- mail giữa các server sử dụng các giao thức giao vận khác nhau. SMTP có khả 20
- năng chuyển tiếp các thông điệp thông qua các môi trường dịch vụ giao vận. SMTP không cho phép chúng ta đọc các thông điệp từ một mail server. POP3-Post Office Protocol POP3 được thiết kế cho các môi trường không được liên kết. Trong các môi trường không duy trì liên kết thường trực với mail server, ví dụ, trong các môi trường trong đó thời gian liên kết lâu. Với POP3, client có thể truy xuất tới server và tìm kiếm các thông điệp mà server hiện đang nắm giữ. Khi các thông điệp được tìm kiếm từ client, chúng thường bị xóa khỏi server, mặc dù điều này là không cần thiết. IMAP-Inernet Message Access Protocol Giống như POP3, IMAP được thiết kế để truy xuất tới các mail trên một mail server. Tương tự như các client POP3, một client IMAP có thể có chế độ offline. Không giống như các client POP3, các client IMAP có các khả năng lớn hơn trên chế độ online, như tìm kiếm các header, các đoạn mail, tìm kiếm các thông điệp cụ thể trên các server, và thiết lập các cờ như cờ trả lời. Về căn bản, IMAP cho phép các client làm việc trên các hộp thư ở xa như là các hộp thư cục bộ. NNTP-Network News Transfer Protocol NNTP là giao thức tầng ứng dụng để gửi, chuyển tiếp, và tìm kiếm các thông điệp tạo nên một phần của các cuộc thảo luận nhóm tin. Giao thức này cung cấp khả năng truy cập tới một server tin tức để tìm kiếm các thông điệp có chọn lọc và hỗ trợ cho việc truyền thông điệp từ server tới server. 3.4. Một số giao thức ứng dụng khác Có hai giao thức ứng dụng thú vị khác là: SNMP và Telnet SNMP (Simple Network Management Protocol) cho phép quản lý các thiết bị trên mạng. Có các thông tin như các biến đếm hiệu năng từ các thiết bị SNMP quản lý các thiết bị một cách hiệu quả bằng cách sử dụng các báo chuông báo hiệu được kích hoạt bởi các vấn đề về hiệu năng và lỗi, và cho phép cấu hình các thiết bị. Một tác tử SNMP được gắn với một thiết bị mạng cụ thể sẽ có một cơ sở dữ liệu MIB (Management Information Base) bao gồm tất cả các thông tin có thể kiểm soát về thiết bị đó theo phương pháp hướng đối tượng. Một client SNMP truy xuất thông tin trong cơ sở dữ liệu bằng cách gửi các yêu cầu GET. Ngược lại, yêu cầu SET được sử dụng để cấu hình cơ sở dữ liệu MIB. Trong những trường hợp có lỗi hoặc có các vấn đề về hiệu năng, tác tử SNMP gửi các thông điệp tới SNMP client. 4. Soket Socket là một phương pháp để thiết lập kết nối truyền thông giữa một chương trình yêu cầu dịch vụ và một chương trình cung cấp dịch vụ trên 21
- mạng LAN, WAN, hay Internet và đôi khi là giữa các tiến trình trong cùng một máy tính. Thông tin của một Socket bao gồm địa chỉ IP và số hiệu cổng. 5. Dịch vụ tên miền Các địa chỉ IP viết dưới dạng 4 nhóm bit không dễ nhớ một chút nào, vì vậy có người ta đã đưa ra một hệ thống tương đương dễ nhớ hơn đối với người sử dụng. Do các tên miền này là duy nhất, nên hệ thống tên miền được sử dụng để hỗ trợ hệ thống tên có phân cấp Như ta đã biết, tiền thân của mạng Internet là mạng Arpanet của Bộ quốc phòng Mỹ. Thời kỳ đó số máy tính ở mức đủ để liệt kê chúng trong một tệp tin văn bản và lưu trên từng máy kết nối vào mạng. Thông tin trong tập tin này bao gồm địa chỉ IP và hostname. Tuy nhiên do quy mô của mạng ngày càng mở rộng người ta cần có các máy tính chuyên dụng để lưu trữ và phân giải tên miền. Các máy tính có chức năng như vậy được gọi là Máy chủ DNS. Ví dụ www.microsoft.com, www.bbc.co.uk. Các tên này không bắt buộc phải có ba phần, nhưng việc đọc bắt đầu từ phải sang trái, tên bắt đầu với miền mức cao. Các miền mức cao là các tên nước cụ thể hoặc tên các tổ chức và được định nghĩa bởi tổ chức IANA. Các tên miền cấp cao được liệt kê trong bảng sau. Trong những năm gần đây, một số tên miền cấp cao mới được đưa vào. Tên Mô tả miền .aero Công nghiệp hàng không .biz Doanh nghiệp .com Các tổ chức thương mại .coop Các quan hệ hợp tác .info Không ràng buộc về sử dụng .museum Các viện bảo tàng .name Các tên cá nhân Bảng 1.7 Tên Mô tả miền .net Các mạng .org Các tổ chức phi chính phủ .pro Các chuyên gia 22
- .gov Chính phủ Hoa Kỳ .edu Các tổ chức giáo dục .mil Quân đội Mỹ .int Các tổ chức được thành lập bởi các hiệp ước quốc tế giữa các chính phủ. Bảng 1.8 Ngoài ra, còn có các tên miền cho các quốc gia Tên Mô tả miền .at Autralia .de Germany .fr France .uk United Kingdom .vn Vietnam Bảng 1.9 5.1. Các server tên miền Các hostname được phân giải bằng cách sử dụng các server DNS (Domain Name Service). Các server này có một cơ sở dữ liệu các hostname và các bí danh ánh xạ các tên thành địa chỉ IP. Ngoài ra, các DNS cũng đăng ký thông tin cho các Mail Server, các số ISDN, các tên hòm thư, và các dịch vụ. Trong Windows, chính các thiết lập TCP/IP xác định server DNS được sử dụng để truy vấn. Lênh ipconfig/all chỉ ra các server DNS đã được thiết lập và các thiết lập cấu hình khác. Khi kết nối với một hệ thống ở xa sử dụng hostname, trước tiên server DNS được truy vấn để tìm địa chỉ IP. Trước tiên, DNS kiểm tra trong bộ cơ sở dữ liệu của riêng nó và bộ nhớ cache. Nếu thất bại trong việc phân giải tên, server DNS truy vấn server DNS gốc. 5.2. Nslookup Dịch vụ tên miền (Domain Name Service) Là tập hợp nhiều máy tính được liên kết với nhau và phân bố rộng trên mạng Internet. Các máy tính này 23
- được gọi là name server. Chúng cung cấp cho người dùng tên, địa chỉ IP của bất kỳ máy tính nào nối vào mạng Internet hoặc tìm ra những name server có khả năng cung cấp thông tin này. Hình 1.9 Cơ chế truy tìm địa chỉ IP thông qua dịch vụ DNS Giả sử trình duyệt cần tìm tập tin hay trang Web của một máy chủ nào đó, khi đó cơ chế truy tìm địa chỉ sẽ diễn ra như sau: 1. Trình duyệt yêu cầu hệ điều hành trên client chuyển hostname thành địa chỉ IP. 2. Client truy tìm xem hostname có được ánh xạ trong tập tin localhost, hosts hay không? -Nếu có client chuyển đổi hostname thành địa chỉ IP và gửi về cho trình duyệt. -Nếu không client sẽ tìm cách liên lạc với máy chủ DNS. 3. Nếu tìm thấy địa chỉ IP của hostname máy chủ DNS sẽ gửi địa chỉ IP cho client. 4. Client gửi địa chỉ IP cho trình duyệt. 5. Trình duyệt sử dụng địa chỉ IP để liên lạc với Server. 6. Quá trình kết nối thành công. Máy chủ gửi thông tin cho client. 6. Internet Trong chương này chúng ta đã đề cập tới nhiều công nghệ cơ sở: phần cứng, các giao thức, và các hệ thống tên miền. Trong phần này chúng ta sẽ thảo luận các vấn đề thú vị khác như: Intranet và Extranet 24
- Firewall và Web Proxy Các dịch vụ Web 6.1. Intranet và Extranet Một intranet có thể sử dụng các công nghệ TCP/IP tương tự như với Internet. Sự khác biệt là intranet là một mạng riêng, trong đó tất cả mọi người đều biết nhau. Intranet không phục vụ cho việc truy xuất chung, và một số dữ liệu cần phải được bảo vệ khỏi những truy xuất từ bên ngoài. Một extranet là một mạng riêng giống như intranet nhưng các extranet kết nối nhiều Intranet thuộc cùng một công ty hoặc các công ty đối tác thông qua Internet bằng cách sử dụng một tunnel. Việc tạo ra một mạng riêng ảo trên Internet tiết kiệm chi phí nhiều cho công ty so với việc thuê riêng một đường truyền để thiết lập mạng. 6.2. Firewall Có những kẻ phá hoại trên mạng Internet!. Để ngăn chặn chúng, người ta thường thiết lập các điểm truy cập tới một mạng cục bộ và kiểm tra tất cả các luồng truyền tin vào và ra khỏi điểm truy nhập đó. Phần cứng và phần mềm giữa mạng Internet và mạng cục bộ, kiểm tra tất cả dữ liệu vào và ra, được gọi là firewall. Firewall đơn giản nhất là một bộ lọc gói tin kiểm tra từng gói tin vào và ra khỏi mạng, và sử dụng một tập hợp các quy tắc để kiểm tra xem luồng truyền tin có được phép vào ra khỏi mạng hay không. Kỹ thuật lọc gói tin thường dựa trên các địa chỉ mạng và các số hiệu cổng. 6.3. Proxy Server Khái niệm proxy có liên quan đến firewall. Nếu mốt một firewall ngăn chặn các host trên mạng liên kết trực tiếp với thế giới bên ngoài. Một máy bị ngăn kết nối với thế giới bên ngoài bởi một firewall sẽ yêu cầu truy xuất tới một trang web từ một proxy server cục bộ, thay vì yêu cầu một trang web trực tiếp từ web server ở xa. Proxy server sau đó sẽ yêu cầu trang web từ một web server, và sau đó chuyển kết quả trở lại cho bên yêu cầu ban đầu. Các proxies cũng được sử dụng cho FTP và các dịch vụ khác. Một trong những ưu điểm bảo mật của việc sử dụng proxy server là các host bên ngoài chỉ nhìn thấy proxy server. Chúng không biết được các tên và các địa chỉ IP của các máy bên trong, vì vậy khó có thể đột nhập vào các hệ thống bên trong. Trong khi các firewall hoạt động ở tầng giao vận và tầng internet, các proxy server hoạt động ở tầng ứng dụng. Một proxy server có những hiểu biết chi tiết về một số giao thức mức ứng dụng, như HTTP và FTP. Các gói tin đi qua proxy server có thể được kiểm tra để đảm bảo rằng chúng chứa các dữ 25
- liệu thích hợp cho kiểu gói tin. Ví dụ, các gói tin FTP chứa các dữ liệu của dịch vụ telnet sẽ bị loại bỏ. Vì tất cả các truy nhập tới Internet được chuyển hướng thông qua proxy server, vì thế việc truy xuất có thể được kiểm soát chặt chẽ. Ví dụ, một công ty có thể chọn giải pháp phong tỏa việc truy xuất tới www.playboy.com nhưng cho phép truy xuất tới www.microsoft.com 26
- Chương 2 Giới thiệu ngôn ngữ lập trình Java 1. Giới thiệu công nghệ Java 1.1Lịch sử phát triển Lịch sử phát triển của Java bắt đầu năm 1991 khi SUN tiến hành các dự án lập trình cho vi xử lý dùng trong các thiết bị điện tử khác nhau. C++ không đáp ứng được các yêu cầu này vì C++ cho đem mã nguồn từ máy này sang máy khác nhưng sau khi biên dịch lại hoàn toàn phụ thuộc vào từng bộ vi xử lý cụ thể. Trong khi đó bộ vi xử lý dùng trong các thiết bị điện tử rất đa dạng và có vòng đời khá ngắn ngủi. Nếu ta thay đổi bộ xử lý dẫn đến cần phải thay đổi trình biên dịch C++, điều này gây lên tốn kém. SUN đã thiết kế một ngôn ngữ lập trình mới có tính khả chuyển cao hơn đó chính là Java. Java là tên địa phương nơi xuất xứ của một loại cà phê ngon nổi tiếng. Java được chính thức công bố năm 1995 và ngay lập tức đã tạo lên một trào lưu mới trên toàn thế giới và từ đó đến nay vẫn tạo được sức cuốn hút mạnh mẽ. Bởi vì Java không chỉ đơn thuần là một ngôn ngữ lập trình mà nó là giải pháp cho nhiều vấn đề. 1.2. Cấu trúc của máy ảo Java (Java Virtual Machine) Chương trình ứng dụng hoạt động bằng cách sử dụng các đối tượng của Java (Java Object). Máy ảo Java tạo thành một cầu nối giữa trình ứng dụng viết bằng Java và hệ điều hành. Chương trình Java: tập hợp các đối tượng Máy ảo Java Hệ điều hành Máy ảo Java bao gồm các thành phần sau : Trình nạp lớp (Class Loader): đọc bytecode từ đĩa hoặc từ kết nối mạng. Trình kiểm tra lớp (Class Verifier): Kiểm tra các lớp sẽ không sinh ra các lỗi ảnh hưởng tới hệ thống khi thực thi. Trình thực thi (Execution Unit): sẽ thực hiện các lệnh được quy định trong từng bytecode. Trong bộ công cụ Java, tệp tin java.exe chính là máy ảo Java. 1.3 Các đặc trưng của Java Java là một môi trường độc lập (Independent Platform) 27
- Do cấu trúc của Java nên ta có thể soạn thảo chương trình trên bất kỳ hệ thống nào. Sau khi đã được biên dịch thành tệp tin lớp (*.class) ứng dụng có thể thực thi ở bất kỳ hệ thống nào. Đó là đặc tính mà các ngôn ngữ khác không có. Java là một ngôn ngữ lập trình hướng đối tượng thuần túy (Pure Object Oriented Programming) Java là một ngôn ngữ lập trình hướng đối tượng thuần túy, mọi thứ trong Java đều là đối tượng. Java là một ngôn ngữ có tính khả chuyển (Portibility) Java có tính khả chuyển đối với cả mã nguồn và bản thân mã biên dịch (bytecode) Java là môi trường xử lý phân tán (Distributed Enviroments) Bytecode không phụ thuộc vào hệ thống vì vậy bytecode có thể nằm phân tán trên mạng. Việc liên kết với thư viện chỉ được thực hiện vào lúc chạy chương trình do vậy mã byte thường gọn nhẹ. Chương trình Java được nạp dần một cách linh hoạt nên không gây quá tải cho mạng. Ngoài ra, Java còn cho phép xử lý đa tuyến đoạn. Cơ chế truyền thông điệp thuận tiện cho việc tổ chức mạng. Java là môi trường an toàn Khi phát triển các ứng dụng phân tán thì một trong nhừng vấn đề được quan tâm hàng đầu là an toàn hệ thống. Java được thiết kế để đảm bảo an toàn cho người dùng Java trên mạng. Java có bốn tầng bảo an: Tầng 1: Mức ngôn ngữ và trình biên dịch. Java không có kiểu con trỏ. Trình biên dịch kiểm tra kiểu rất chặt chẽ. Mọi chuyển đổi kiểu đều phải được thực hiện một cách tường minh. Trình biên dịch Java từ chối sinh ra mã byte nếu mã nguồn không tuân thủ nghiêm ngặt các quy tắc an toàn. Tầng 2: Trình nạp lớp (Class Loader) Có khả năng phân biệt những lớp đến từ mạng và những lớp nạp từ hệ thống. Nhờ khả năng phân biệt như vậy lớp được nạp qua mạng được khống chế chặt chẽ, không được phép thực hiện các thao tác mức thấp. Tầng 3: Trình kiểm tra mã byte. Trình này sẽ kiểm tra mã byte vào lúc chạy chương trình bảo đảm chương trình Java đã được biên dịch một cách đúng đắn. Khi thực hiện sẽ không gây lỗi ảnh hưởng tới hệ thống cũng như không đụng chạm tới dữ liệu riêng tư trên máy khách. Tầng 4: Trình bảo an. Kiểm tra mã byte vào lúc chạy nhằm bảo đảm mã đang xét không vi phạm qui tắc an toàn đã được thiết lập. Các thao tác của ứng dụng được xem là có khả năng gây nguy hiểm như đọc, xóa tệp đều phải được Trình bảo an cho phép. Java cung cấp cho người lập trình một thư viện khủng lồ 28
- Java cung cấp cho người lập trình một thư viện khổng lồ các hàm chuẩn, gọi là core API. Các hàm chuẩn này được đặt trong các gói. Java có cơ chế quản lý bộ nhớ tự động Quản lý bộ nhớ là một trong những vấn đề phức tạp đối với C và C++. Khi thực hiện chương trình người lập trình chịu trách nhiệm khởi tạo các vùng nhớ, sau khi dùng phải giải phóng các vùng nhớ này. Chỉ cần một lỗi nhỏ có thể làm cạn kiệt tài nguyên dẫn đến treo hệ thống. Java đã loại bỏ gánh nặng này cho người lập trình. Các vùng nhớ được tự động giải phóng nếu như nó không tham chiếu đến bất kỳ đối tượng nào đang hoạt động Chi phí phát triển ứng dụng bằng Java thấp Khi phát triển ứng dụng dựa trên công nghệ Java thì sẽ có rất nhiều công cụ phát triển và dịch vụ được cung cấp miễn phí. 1.4. Các ấn bản Java J2SE ( Java 2 Platform, Second Edition) Đây là ấn bản chuẩn, bao gồm một môi trường thời gian chạy và một tập hợp các API để xây dựng một loạt các ứng dụng khác nhau từ applet, cho tới các ứng dụng độc lập chạy trên các nền khác nhau, ứng dụng cho client cho các ứng dụng doanh nghiệp khác nhau. J2EE (Java 2 Platform, Enterprise Edition (J2EE) J2EE là nền tảng để xây dựng các ứng dụng phía server. J2ME (Java 2 Platform, Micro Edition ) Ấn bản này cho phép xây dựng các ứng dụng Java cho các “vi thiết bị” (các thiết bị có màn hình hiển thị và hỗ trợ bộ nhớ tối thiểu, như điện thoại di động và các thiết bị trợ giúp cá nhân). 1.5. Công cụ phát triển SUN cung cấp một số tiện ích cho phép biên dịch bắt lỗi và tạo tài liệu cho một ứng dụng Java. JDK bao gồm: javac: Bộ biên dịch để chuyển mã nguồn thành bytecode. java: Bộ thông dịch để thực thi các ứng dụng Java trực tiếp từ tập tin lớp. apppletviewer: Thực thi Java Applet từ tài liệu html. 1.6. Các kiểu ứng dụng trong Java Có hai kiểu ứng dụng Ứng dụng độc lập (Standalone Applicaiton) Cho phép lập trình như các ngôn ngữ lập trình khác như Pascal, C. 29
- Ứng dụng ký sinh (Applet) Cho phép tạo ra chương trình liên kết với các văn bản Web và được khởi động bởi trình duyệt hỗ trợ Java. Để thấy được sự khác biệt giữa hai kiểu ứng dụng nói trên chúng ta có thể xem những sự khác biệt về đặc trưng của hai kiểu ứng dụng ở bảng dưới đây: Ứng dụng độc lập Java Applet Khai báo Là lớp con của bất kỳ lớp Phải là lớp con của nào trong các gói thư viện Applet các lớp Giao diện đồ họa Tùy chọn Do trình duyệt Web quyết định Yêu cầu bộ nhớ Bộ nhớ tối thiểu Bộ nhớ dành cho cả trình duyệt và applet đó Cách nạp chương Nạp bằng dòng lệnh Thông qua trang Web trình Dữ liệu vào Thông qua các tham số trên Các tham số đặt trong dòng lệnh tệp HTML gồm địa chỉ, kích th-ớc của trình duyệt Cách thức thực hiện Mọi hoạt động được bắt đầu Gọi các hàm: init(), và kết thúc ở main() nh- start(), stop(), destroy(), trong C/C++ paint() Kiểu ứng dụng Ứng dụng trên các máy chủ Các ứng dụng trên Web Server. Công cụ phát triển phần mềm, - ứng dụng trên các máy khách Bảng 2.1 1.7. Cài đặt chương trình dịch Java và các công cụ Để cài đặt Java J2SDK ta cần tải về bộ J2SDK tại trang , trang này cập nhật những phiên bản mới nhất của Java. Sau đó ta tải về bộ công cụ soạn thảo Edit Plus tại địa chỉ . Các bước cài đặt Java Bước 1: Cài đặt J2SDK. Sau khi cài đặt xong, Java được cài đặt tại thư mục: 30
- C:\Program Files\Java. Trong thư mục này có hai thư mục con là: jdk1.5.0_01 và jre1.5.0_01. Công cụ phát triển nằm trong thư mục: C:\Program Files\Java\jdk1.5.0_01\bin: Bao gồm các công cụ cho phép ta phát triển, thực thi, gỡ rối và soạn thảo các chương trình được viết bằng ngôn ngữ lập trình Java. Môi trường thời gian chạy (Runtime Environment) Nằm trong thư mục con JRE. Nó bao gồm một máy ảo Java, các thư viện lớp, và các tệp tin hỗ trợ việc xử lý các chương trình được viết bằng ngôn ngữ lập trình Java. Các thư viện Nằm trong thư mục con lib. Các thư viện lớp và các tệp tin bổ trợ cần cho các công cụ phát triển Các ứng dụng và applet demo Nằm trong thư mục demo. Thư mục này bao gồm các ví dụ, mã nguồn lập trình cho Java/ Bước 2: Thiết lập các biến môi trường Biến môi trường path Trên desktop ta kích chuột phải vào biểu tượng My Computer, sau đó chọn thẻ Advanced, nháy chuột vào nút lệnh Enviroment Variable, xuất hiện cửa sổ cho phép ta thiết lập biến môi trường như sau: 31
- Hình 2.1 Nháy vào nút lệnh New để nhập vào thông tin về biến môi trường Hình 2.2 Sau đó nháy chuột vào nút lệnh OK để hoàn thành Thiết lập biến môi trường classpath cũng tiến hành tương tự Hình 2.3 Bước 3: Cài đặt chương trình soạn thảo Edit Plus. Bước 4: Tạo lập các công cụ biên dịch và thực thi chương trình trong Edit Plus. Giao diện của chương trình soạn thảo như sau: 1.8. Một số ví dụ mở đầu Ví dụ 1: Tạo chương trình Java cho phép nhập một dòng ký tự từ đối dòng lệnh và hiển thị xâu ký tự đó lên trên màn hình: class ViDu1 { public static void main(String[] args) { System.out.println(args[0]); } 32
- } Biên dịch chương trình C:\>javac ViDu1.java Thực hiện chương trình C:\>java ViDu1 "Lam quen voi ngon ngu lap trinh Java" Kết quả in ra là: Lam quen voi ngon ngu lap trinh Java Chương trình trên ta nhận thấy ngay đây là một chương trình ứng dụng độc lập đơn giản. Chương trình thực hiện một tác vụ hết sức đơn giản là nhận một xâu ký tự được truyền vào từ đối dòng lệnh sau đó in xâu ký tự lên màn hình. Đối dòng lệnh là một mảng xâu ký tự String[] args. Khi ta thực thi chương trình trên, args[0] được gán bằng xâu ký tự "Lam quen voi ngon ngu lap trinh Java". Ví dụ 2: Tạo một applet hiển thị một xâu ký tự lên màn hình import java.applet.*; import java.awt.*; public class ViDu2 extends Applet { public void paint(Graphics g) { g.drawString("Chuc mung cac ban da thanh cong voi vi du thu 2",30,30); } } Biên dịch applet C:\>javac ViDu2.java Tạo một trang html để nhúng applet New Document 33
- Trong tài liệu trên ta để ý thấy dòng cho phép ta nhúng một applet trong một văn bản web. Để thực thi applet ta chỉ cần hiển thị trang ViDu2.html trên trình duyệt. Kết quả được thể hiện ở hình dưới đây: Hình 2.4 2. Ngôn ngữ lập trình Java 2.1 Cấu trúc tệp của một chương trình Java Một tệp tin chương trình Java có thể có các phần được đặc tả như sau: 1. Định nghĩa một gói là tùy chọn thông qua định danh của gói (package). 2. Một số lệnh nhập import (0 hoặc nhiều). 34
- 3. Một số định nghĩa lớp và interface có thể định nghĩa theo thứ tự bất kỳ Ví dụ giả sử có tệp nguồn Java như sau: // Phần 1: Tùy chọn // Định nghĩa gói package GoiNhaTruong; // Phần 2: (0 hoặc nhiều hơn) // các gói cần sử dụng import java.io.*; // Phần 3: (0 hoặc nhiều hơn) // Định nghĩa các lớp và các interface public class NewApp{ } class C1{ } interface I1{ } // class Cn { } interface Im{ } Hình 2.5 Lưu ý: Tệp chương trình Java luôn có tên trùng với tên của một lớp công khai (lớp chứa hàm main() nếu là ứng dụng độc lập) và có phần mở rộng là .java. Tệp NewApp.java nếu là chương trình ứng dụng độc lập thì phải có một lớp có tên là NewApp và lớp này phải có phương thức main(). Phương thức này luôn có dạng: public static void main(String args[]){ // Nội dung cần thực hiện của chương trình ứng dụng } Khi dịch (javac) thì mỗi lớp trong tệp chương trình sẽ được dịch thành byte code và được ghi thành tệp riêng có tên trùng với tên của lớp và có đuôi .class. Những lớp này sẽ được nạp vào chương trình lúc thông dịch và thực hiện theo yêu cầu. Trong chương trình Java không có các khai báo biến, hàm tách biệt khỏi lớp và chỉ có các khai báo và định nghĩa các lớp, interface. Như thế chương trình Java được xem như là tập các lớp, interface và các đối tượng của chúng trao đổi thông điệp với nhau (bằng các lời gọi hàm) để thực hiện các nhiệm vụ của ứng dụng. 2.2. Định danh, kiểu dữ liệu và khai báo biến 35
- Định danh (Identifier) Tên gọi của các thành phần trong chương trình được gọi là định danh Định danh thường được sử dụng để xác định biến, kiểu, phương thức, lớp. Qui tắc cho định danh: Định danh là một dãy các ký tự gồm các chữ cái, chữ số và các ký tự khác: ‘_’, $, Định danh không bắt đầu bằng chữ số. Độ dài của định danh không giới hạn. Java phân biệt chữ hoa và chữ thường. Qui ước đặt tên Định danh cho các lớp: chữ cái đầu của mỗi từ trong định danh đều viết hoa Ví dụ: MyClass, HocSinh, SocketServer, URLConnection, Định danh cho các biến, phương thức, đối tượng: chữ cái đầu của mỗi từ trong định danh đều viết hoa trừ từ đầu tiên. Ví dụ: hoTen (họ tên), namSinh (năm sinh), tinhTong (tính tổng). Chú thích Chú thích trong các chương trình để giải thích công việc hoặc cách thực hiện để người đọc dễ hiểu và tiện theo dõi. Chú thích trên một dòng //Đây là chú thích dòng Chú thích trên nhiều dòng /* Đây là chú thích khối nhiều dòng */ 2.3. Các kiểu dữ liệu nguyên thủy (primitive datatype) Kiểu dữ liệu cơ bản định nghĩa sẵn được gọi là kiểu nguyên thủy Kiểu nguyên thủy bao gồm các kiểu: 36
- Hình 2.6 Kiểu nguyên: char (ký tự), byte, short, int, long. Kiểu số thực: float, double. Kiểu logic: boolean. Kiểu dữ liệu Độ rộng char 16 byte 8 short 16 int 32 long 64 float 32 doube 64 Bảng 2.2 Chú ý: Các giá trị kiểu nguyên thủy không phải là đối tượng. Mỗi kiểu dữ liệu có miền xác định và các phép toán xác định trên nó. Mỗi kiểu dữ liệu nguyên thủy có một lớp gói (wrapper class) để sử dụng các kiểu nguyên thủy như là các đối tượng. Kiểu dữ liệu Lớp gói char Char 37
- byte Byte short Short int Integer long Long float Float double Double Bảng 2.3 2.4. Khai báo các biến a. Các loại biến trong Java Các biến thành phần: là các thành phần của lớp và được khởi tạo giá trị mỗi khi một đối tượng của lớp được tạo ra. Ví dụ: URL u ; HocSinh hs = new HocSinh(“Tuan Anh”); Các biến tham chiếu đối tượng (Object Reference) là biến được sử dụng để xử lý các đối tượng. Các biễn tĩnh (static variable) là biến của lớp đại diện cho cả lớp. Các biến cục bộ: là biến được khai báo trong các phương thức và trong các khối. b. Khai báo biến kieu_du_lieu bien; Ví dụ: int i; char b,c; float giaBan, dienTich; c. Khởi tạo giá trị cho các biến Các giá trị mặc định cho các biến thành phần Kiểu dữ liệu Giá trị mặc định boolean false char ‘\u000’ byte, short, int, long 0 float, double +0.0F,+0.0D tham chiếu đối tượng null 38
- Bảng 2.4 Qui tắc chuyển đổi kiểu trong Java ( ) Ví dụ float f = (float)100.15D; Mở rộng và thu hẹp kiểu byte short int long float double char Ví dụ 1:Mở rộng kiểu char c = ‘A’; int k =c; Ví dụ 2:Thu hẹp kiểu int k =10; char c=(char)k; 2.3. Các lệnh trong Java Một lệnh có thể thay đổi trạng thái của máy tính: giá trị của các biến, các phần tử của mảng, nội dung của các tệp tin, 2.3.1. Lệnh biểu thức Một lệnh biểu thức là lệnh có dạng: ; Nó được xử lý bằng cách đánh giá biểu thức mà không cần lưu lại giá trị tính toán. 2.3.2. Khối lệnh Khối lệnh trong Java tương tự như khối lệnh trong C/C++, là những lệnh nằm trong cặp ngoặc mở { và đóng }. Một khối lệnh là một dãy không hoặc nhiều lệnh hoặc các khai báo biến hoặc khai báo lớp theo bất kỳ thứ tự nào được đặt trong cặp ngoặc {} { S1; S2; 39
- Sn; } . Lệnh gán Ví dụ int a, b, c,d; d=b*b-4*a*c; Biểu thức điều kiện Biểu thức điều kiện A?B:C trả về giá trị B nếu A có giá trị true, trả về giá trị C nếu A có giá trị false. Ví dụ: byte b; int i=b>=0?b:b+255; Trong ví dụ trên thực hiện việc chuyển đổi các số nguyên kiểu byte có dấu về số nguyên kiểu int không có dấu. Nếu b lớn hơn hoặc bằng 0 thì I nhận giá trị là b, ngược lại I sẽ nhận giá trị là 255+b. 2.3.4. Các lệnh điều khiển rẽ nhánh chương trình o Lệnh if đơn giản Cú pháp if o Lệnh if – else Cú pháp if ; else ; Ví dụ: Viết chương trình nhập vào một dãy số nguyên từ đối dòng lệnh, sắp xếp dãy số đó và hiển thị dãy số sau khi sắp xếp lên màn hình. class SapXep { public static void main(String[] args) { int a[]=null; int i,j,tg; if(args.length>0) { a=new int[args.length]; 40
- } for(i=0;i a[j]) { tg=a[i]; a[i]=a[j]; a[j]=tg; } System.out.println("Day so sau khi sap xep la:"); for(i=0;i javac SapXep.java Thực hiện chương trình C:\>java SapXep -2 3 1 4 -5 6 -10 -2 3 1 4 -5 6 -10 Day so sau khi sap xep la: -10 -5 -2 1 3 4 6 Lệnh switch Lệnh này cho phép rẽ nhánh theo nhiều nhánh tuyển chọn dựa trên các giá trị nguyên của biểu thức. Cú pháp: switch( ) 41
- { case nhan_1: ; case nhan_2: ; case nhan_3: ; case nhan_n: ; default: ; } 2.3.5. Lệnh lặp Lệnh lặp cho phép một khối các câu lệnh thực hiện một số lần lặp lại. Lệnh while while ( ) Chú ý: Có thể không được thực hiện lần nào nếu ngay từ đầu có giá trị false. là biểu thức boolean. Ví dụ: Lập chương trình in ra dãy số Fibonaci có các giá trị nhỏ hơn 50. class Fibonaci { public static void main(String[] args) { int lo=1; int hi =1; System.out.println(lo); while(hi<50) { System.out.println(hi); hi=lo+hi; lo=hi-lo; } } } 42
- Lệnh do – while Cú pháp do { //Các lệnh } while( ); Chú ý: Thân chu trình được thực hiện ít nhất một lần Lệnh for Cú pháp for( ; ; ) o : Khai báo và gán các giá trị khởi đầu cho các biến điều khiển quá trình lặp. o :Biếu thức logic. Sự tương đương giữa vòng for và while { ; while( ) { ; ; } Lệnh lặp vô hạn: Ta có thể sử dụng vòng for với cú pháp như sau làm vòng lặp vô hạn. for(;;) Vòng lặp vô hạn while: while(true){ } 2.3.6. Các câu lệnh nhảy Java hỗ trợ ba lệnh nhảy: break, continue, và return. Các lệnh này truyền điều khiển sang phần khác của chương trình. 43
- Lệnh break: Được dùng để kết thúc trình tự thực hiện lệnh trong lệnh switch hoặc được sử dụng để thoát ra khỏi một vòng lặp. class BreakDemo { public static void main(String[] args) { for(int i=0;i<20;i++){ if(i==10)break; System.out.println("i="+i); } } } Chương trình này in ra kết quả là: i=0 i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 Như chúng ta có thể thấy, vòng lặp for được thiết kế để chạy với các giá trị từ 0 đến 9, lệnh break làm cho vòng lặp kết thúc sớm khi i bằng 10. Lệnh break có thể được sử dụng trong bất kỳ vòng lặp Java nào, bao gồm cả vòng lặp vô hạn Lệnh continue Lệnh continue sẽ bỏ qua không xử lý một lệnh nào đó trong vòng lặp nhưng vẫn tiếp tục thực hiện phần còn lại của vòng lặp. class ContinueDemo { public static void main(String[] args) 44
- { for(int i=0;i<20;i++){ if(i==10)continue; System.out.println("i="+i); } } } Kết quả thực hiện chương trình trên như sau: i=0 i=1 i=2 i=3 i=4 i=6 i=7 i=8 i=9 Ta thấy rằng chương trình không in ra giá trị i=5 vì khi kiểm tra điều kiện chương trình bỏ qua giá trị i=5 và thực hiện lệnh với giá trị I còn lại của vòng lặp. Lệnh return Được sử dụng để kết thúc việc thực hiện của hàm hiện thời và chuyển điều khiển chương trình về cho chương trình đã gọi phương thức Ví dụ protected double giaTriKhongAm(double v) { if(v<0) return 0; else return v; } 2.4 Các lớp và các đối tượng trong Java 45
- Đơn vị cơ bản trong lập trình Java là lớp. Các lớp bao gồm các phương thức thực hiện công việc tính toán. Các lớp cũng đưa ra cấu trúc của đối tượng và cơ chế tạo ra đối tượng từ các định nghĩa lớp. 2.4.1. Cấu trúc chung của một lớp [ ] class [extends ] [implements ] { } Khuôn mẫu của một lớp kiểu_dữ_liệu1 biến1 kiểu_dữ_liệu2 biến2 kiểu_dữ_liệun biếnn phương_thức1() phương_thức2() phương_thứcm() Các kiểu lớp trong Java Lớp có sẵn (built-in). Lớp do người dùng định nghĩa (user-defined) Định nghĩa phương thức Hành vi của các đối tượng của một lớp được xác định bởi các phương thức của lớp đó. Cú pháp định nghĩa phương thức [ ] ([ ])[ ] { 46
- } Trong đó có thể là kiểu nguyên thủy, kiểu lớp hoặc không có giá trị trả lại (kiểu void) bao gồm dãy các tham biến (kiểu và tên) phân cách với nhau bởi dấu phẩy. Các kiểu phạm vi hay kiểm soát truy cập . public: Các thành phần được khai báo là public có thể được truy cập ở bất kỳ nơi nào có thể truy cập được và chúng được thừa kế bởi các lớp con của nó. . private: Các thành phần được khai báo là private chỉ có thể được truy cập trong chính lớp đó . protected: Các thành phần được khai báo là protected có thể được truy cập và thừa kế bởi các lớp con và có thể truy xuất bởi mã lệnh của cùng gói đó. Constructor Constructor là một phương thức đặc biệt không có giá trị trả về và có tên trùng với tên lớp. Trường hợp không có constructor nào được đưa ra trình biên dịch cung cấp constructor mặc định cho lớp đó. Một đối tượng được tạo mới và được cho trước một giá trị khởi đầu. Các trường có thể được khởi tạo bằng một giá trị khi chúng được khai báo, điều này đủ để đảm bảo một trạng thái khởi đầu đúng đắn. Các phương thức Các phương thức của một lớp thường chứa mã có thể hiểu và thao tác một trạng thái của đối tượng. Một số lớp có các trường public để người lập trình có thể thao tác trực tiếp, nhưng trong hầu hết các trường hợp điều này không phải là một ý tưởng tốt. public class Point { protected double x,y; public Point(double x,double y) { 47
- this.x=x; this.y=y; } public void move(double dx, double dy) { x=x+dx; y=y+dy; } public void print() { System.out.println("x="+x+", y="+y); } public static void main(String[] args) { Point p=new Point(3.0,6.0); System.out.println("Thong tin ve toa do diem ban dau:"); p.print(); p.move(-1.5,2.0); System.out.println("Thong tin ve toa do diem sau khi tinh tien theo vec to:"); p.print(); } } C:\>java Point Thong tin ve toa do diem ban dau: x=3.0, y=6.0 Thong tin ve toa do diem sau khi tinh tien theo vec to: x=1.5, y=8.0 Tham chiếu this Thông thường, đối tượng nhận phương thức cần phải biết tham chiếu của nó. Trong lớp Point có constructor public Point(double x,double y) 48
- { this.x=x; this.y=y; } Giả sử nếu sửa đổi constructor bằng cách thay đổi như sau: public Point(double x,double y) { x=x; y=y; } Khi biên dịch chương trình sẽ báo lỗi vì có sự nhập nhằng trong các lệnh gán. Tham chiếu this đã khắc phục được điều này, this.x và this.y muốn đề cập tới trường thông tin của lớp Point còn x, y là tham biến truyền vào của constructor. 2.4.2. Thừa kế trong Java class Point3C extends Point2C { protected double z; public Point3C(double x, double y, double z) { super(x,y); this.z=z; } public void move(double dx, double dy, double dz) { super.move(dx,dy); z+=dz; } public void print() { 49
- super.print(); System.out.print(" z="+z); } public static void main(String[] args) { Point3C p=new Point3C(3.0,4.5,5.0); System.out.println("Toa do ban dau:"); p.print(); System.out.println(); p.move(-1.0,0.5,-1.0); System.out.println("Toa do sau khi tinh tien:"); p.print(); System.out.println(); } } Từ khóa super Từ khóa super được sử dụng để gọi constructor của lớp cha hoặc truy xuất tới các thành phần của lớp cha được che dấu bởi một thành phần của lớp con. Ở trên ta đã xét hai đoạn mã, đoạn mã thứ nhất khai báo lớp Point2C biểu diễn một đối tượng điểm hai chiều, đoạn mã thứ hai khai báo lớp Point3C biểu diễn một đối tượng điểm ba chiều. Lớp Point3C được kế thừa lớp từ lớp Point2C. Lời gọi super(x,y) trong lớp Point3C gọi tới constructor Point2C hay super.move(dx,dy) gọi tới phương thức move(dx,dy) của lớp Point2C. Biên dịch chương trình C:\>javac Point3C.java Thực thi chương trình C:\>java Point3C Kết quả chương trình Toa do ban dau: x=3.0, y=4.5 z=5.0 Toa do sau khi tinh tien: 50
- x=2.0, y=5.0 z=4.0 2.4.3. Truyền tham số trong Java Thông thường, trong một ngôn ngữ lập trình thường có hai cách truyền tham biến cho một thủ tục: truyền theo tham trị và truyền theo tham chiếu. Truyền theo tham trị Phương thức sẽ sao chép giá trị của một tham biến vào tham biến hình thức của thủ tục. Vì vậy, những thay đổi đối với tham số thủ tục sẽ không ảnh hưởng tới tham số thực sự. class CallByValue { void test(int i,int j) { i*=2; j*=2; } public static void main(String[] args) { CallByValue cbl=new CallByValue(); int a=10, b=30; System.out.println("Gia tri a va b truoc khi goi phuong thuc:"+a+" "+b); cbl.test(a,b); System.out.println("Gia tri a va b truoc sau goi phuong thuc:"+a+" "+b); } } C:\MyJava>javac CallByValue.java C:\MyJava>java CallByValue Gia tri a va b truoc khi goi phuong thuc:10 30 Gia tri a va b truoc sau goi phuong thuc:10 30 Tất cả các tham số đối với các phương thức Java là “gọi theo trị”. Nghĩa là, các giá trị của các biến tham số trong một phương thức là các bản sao của các giá trị do người gọi xác định. 51
- Ví dụ: class TruyenThamTri { public static void main(String[] args) { double one =1.0; System.out.println("Truoc khi goi ham:one="+one); chia(one); System.out.println("Sau loi goi ham chia:one ="+one); } public static void chia(double x) { x/=2.0; System.out.println("Sau khi chia:x="+x); } } C:\MyJava\Baitap>java TruyenThamTri Truoc khi goi ham:one=1.0 Sau khi chia:x=0.5 Sau loi goi ham chia:one =1.0 Truyền theo tham chiếu Một tham chiếu tới tham biến được truyền cho tham số. Bên trong thủ tục, tham chiếu này được sử dụng để truy xuất tới tham số thực sự được xác định trong lời gọi. Điều này nghĩa là những thay đổi đối với tham biến sẽ ảnh hưởng tới tham số đã được sử dụng để gọi phương thức. Mảng trong Java được xem là đối tượng. Các phần tử của mảng có thể có kiểu nguyên thủy hoặc kiểu tham chiếu (kiểu lớp) Ví dụ: Lọc ra phần tử lớn nhất của một mảng và đưa về cuối mảng. C:\MyJava\Baitap>java Loc 8 1 4 3 2 5 1 4 3 2 5 8 52
- Vì trong Java các lời gọi hàm đều thực hiện theo tham trị (call by value) với kiểu nguyên tố và tham chiếu đối với kiểu lớp nên hàm doiCho() thay đổi được các phần tử của day. Các tham biến final Tham biến hình thức có thể được khai báo với từ khóa final đứng trước. Tham biến final là tham biến không được khởi tạo giá trị cho đến khi nó được gán một trị nào đó và khi đã được gán trị thì không thể thay đối giá trị đó được. Ví dụ class BienFinal { public static void main(String[] args) { HangSX banh = new HangSX(); int giaBan=20; double tien = banh.tinh(10,giaBan); System.out.println("Gia ban: "+giaBan); System.out.println("Tien ban duoc: "+tien); } } class HangSX { double tinh(int so, final double gia) { gia = gia/2.0; return so*gia; } }; Khi biên dịch hàm tinh(), chương trình dịch sẽ thông báo lỗi và không được phép thay đổi giá trị của biến final gia. Các đối trong chương trình Chúng ta có thể truyền các tham số cho chương trình trên dòng lệnh Ví dụ 53
- class TinhTong { public static void main(String[] args) { float s=0.0f; for(int i=0; i java TinhTong 12 34 56 Tong cua day so la 102.0 2.4.4. Đa hình trong Java Các phương thức nạp chồng (overloaded method) Các phương thức nạp chồng là các phương thức nằm trong cùng một lớp có cùng tên nhưng khác nhau về danh sách tham số. Các phương thức nạp chồng là một dạng của tính đa hình thời gian biên dịch. Ví dụ class TinhToan { public static void main(String[] args) { Tinh c = new Tinh(); c.add(10,20); c.add(40.0f,35.65f); c.add("Good ","Morning"); } } class Tinh 54
- { public void add(int a, int b) { int c = a+b; System.out.println("Phep cong hai so nguyen :"+c); } public void add(float a, float b) { float c = a+b; System.out.println("Phep cong hai so dau phay dong :"+c); } public void add(String a, String b) { String c = a+b; System.out.println("Phep cong hai xau :"+c); } }; Kết quả: C:\MyJava\Baitap>java TinhToan Phep cong hai so nguyen :30 Phep cong hai so dau phay dong :75.65 Phep cong hai xau :Good Morning Giải thích: Trong chương trình trên phương thức add() là phương thức được nạp chồng. Có ba phương thức có cùng tên add() nhưng có các tham số khác nhau. Khi chúng ta gọi phương thức add() ???? 2.4.5. Các thành phần static Đôi khi các thành phần static ta cần phải định nghĩa các thành phần lớp được sử dụng độc lập với bất kỳ đối tượng nào của lớp. Thông thường một thành phần của lớp phải được truy xuất thông qua đối tượng của lớp. Tuy nhiên, ta có thể có thể tạo ra một thành phần mà được sử dụng độc lập. Để tạo ra một thành phần như vậy trước khai báo của mỗi thành phần ta đặt một từ khóa static. Khi một thành phần được khai báo static, nó có thể được truy xuất trước khi một đối tượng được tạo ra và không cần tham chiếu tới bất kỳ đối tượng nào. Các thành phần static bao gồm: biến static, phương thức static, khối static. 55
- Biến static Biến static về cơ bản là biến tổng thể. Khi các đối tượng của một lớp được khai báo, không có bản sao của biến đối tượng nào được tạo ra. Thay vào đó, tất cả các đối tượng cùng chung một biến static. Ví dụ về biến static class StaticVariable { static int count=20; StaticVariable(){ count++; } public static void main(String[] args) { StaticVariable c1=new StaticVariable(); System.out.println("Bien dem count="+count); StaticVariable c2=new StaticVariable(); System.out.println("Bien dem count="+count); StaticVariable c3=new StaticVariable(); System.out.println("Bien dem count="+count); } } Biến count được khai báo là static nên nó chỉ có một bản sao trong mọi đối tượng, vì vậy khi đối tượng được tạo ra thì các biến count được tăng lên 1 do trong hàm constructor biến count được tăng lên 1. Phương thức static Các phương thức được khai báo static có một số hạn chế sau: o Chúng chỉ có thể gọi các phương thức static khác. o Chúng chỉ truy xuất tới các dữ liệu static o Chúng không thể tham chiếu tới this và super Ví dụ class StaticMethod { public static void main(){ System.out.println("Hello"); } 56
- public static void main(String[] args) { main(); System.out.println("Hello World!"); } } Trong ví dụ này ta thấy khai báo hai phương thức main đều là phương thức tĩnh. Phương thức main này gọi tới phương thức main khác. Khối static Nếu cần tính toán để khởi tạo các biến static, ta có thể khai báo khối static để nó có thể xử lý ngay tức thời khi lớp lần đầu tiên được tải vào bộ nhớ. Các khối static luôn được xử lý trước Ví dụ class StaticDemo { static{ System.out.println("Khoi static 1"); } public static void main(String[] args) { System.out.println("Hello World!"); } static { System.out.println("Khoi static 2"); } } Vì khối static luôn được xử lý trước nên kết quả in ra của chương trình trên sẽ là: Khoi static 1 Hello World! Khoi static 2 57
- 2.4.6. Các thành phần final Biến final Một biến được khai báo final. Làm như vậy sẽ ngăn ngừa nội dung của biến bị sửa đổi. Điều này nghĩa là ta phải khai báo một biến final khi nó được khai báo. Ví dụ final double pi=3.1416; Sử dụng final với thừa kế Mặc dù nạp chồng phương thức là một trong các đặc trưng mạnh của Java, nhưng sẽ có những lúc ta cần ngăn ngừa điều này xảy ra. Để không cho phép một phương thức được nạp chồng, xác định từ khóa final như là một bổ từ tại đầu mỗi khai báo của nó. Các phương thức được khai báo là final không thể được nạp chồng. Ví dụ class A { final void method(){ } } class B extends A{ final void method(){ } } Khai báo lớp B có lỗi, vì ở lớp A, phương thức method đã được khai báo với từ khóa final nên nó không thể được nạp chồng trong lớp B. Sử dụng từ khóa final để cấm thừa kế Đôi khi ta cần cấm một số lớp không có lớp con. Ta có thể thực hiện điều này bằng cách khai báo lớp với từ khóa final. Ví dụ final class A { } Lúc này, các lớp khác không thể thừa kế từ lớp A. 2.5. Các lớp trừu tượng Trong lập trình Java, có những lúc ta cần định nghĩa lớp cha và khai báo cấu trúc một cách khái quát mà không cài đặt cụ thể cho từng phương thức. Các lớp cha sẽ định nghĩa dạng tổng quát hóa được dùng chung bởi các lớp 58
- con của nó, việc cài đặt chi tiết các phương thức này sẽ được thực hiện ở trong từng lớp con cụ thể. Ví dụ: abstract class Hinh2D { double a,b,r; public abstract double dientich(); public abstract double chuvi(); } class HinhTron extends Hinh2D { public HinhTron(double r) { this.r=r; } public double dientich() { return Math.PI*r*r; } public double chuvi() { return Math.PI*2*r; } } class HinhChuNhat extends Hinh2D { public HinhChuNhat(double a,double b) { this.a=a; this.b=b; } public double dientich() { 59
- return a*b; } public double chuvi() { return (a+b)*2; } } class AbstractDemo { public static void main(String args[]) { Hinh2D ht=new HinhTron(1); System.out.println("Dien tich hinh tron ban kinh 1.0 la:"+ht.dientich()); System.out.println("Chu vi hinh tron ban kinh 1.0 la:"+ht.chuvi()); Hinh2D hcn=new HinhChuNhat(3,4); System.out.println("Dien tich hinh chu nhat la:"+hcn.dientich()); System.out.println("Chu vi hinh chu nhat la "+hcn.chuvi()); } }; Kết quả thực hiện chương trình C:\MyJava>java AbstractDemo Dien tich hinh tron ban kinh 1.0 la:3.141592653589793 Chu vi hinh tron ban kinh 1.0 la:6.283185307179586 Dien tich hinh chu nhat la:12.0 Chu vi hinh chu nhat la 14.0 Trong chương trình trên ta khai báo lớp trừu tượng Hinh2D, lớp này có các phương thức trừu tượng là dientich() để tính diện tích của hình và lớp chuvi() để tính chu vi. Các lớp trừu tượng không được cài đặt mã lệnh. Các lớp HinhTron và HinhChuNhat là các lớp con cụ thể của lớp trừu tượng Hinh2D. Các lớp này cài đặt các phương thức tính diện tích và chu vi cụ thể 60
- 2.6. Giao tiếp (Interface) Thừa kế đóng một vai trò rất quan trọng trong việc tiết kiệm thời gian và công sức của người lập trình. Hầu hết các chương trình trong thực tế đều sử dụng đa thừa kế. Trong đa thừa kế, chúng ta có thể thừa kế các phương thức và thuộc tính từ một số lớp khác nhau. Java không hỗ trợ đa thừa kế. Tuy nhiên, nhận thấy tầm quan trọng của đa thừa kế trong Java, Java đã đưa ra khái niệm interface. Với giao tiếp ta có thể xác định một lớp phải làm gì nhưng không xác định cách làm thế nào. Định nghĩa Một giao tiếp là một tập hợp các định nghĩa phương thức (không có cài đặt). Một giao tiếp cũng có thể định nghĩa các hằng. Ta cũng có thể đặt câu hỏi vậy giao tiếp khác gì so với các lớp trừu tượng? Dưới đây là những sự khác biệt giữa giao tiếp và các lớp trừu tượng: o Một giao tiếp không thể thực thi bất kỳ phương thức nào, ngược lại một lớp trừu tượng có thể thực thi một số phương thức nào đó. o Một lớp có thể thực thi nhiều giao tiếp nhưng một lớp chỉ có một lớp cha. o Một giao tiếp không phải là bộ phận của sơ đồ phân cấp lớp, các lớp có thể thực thi cùng một giao tiếp. Khai báo một giao tiếp Cú pháp chung khi khai báo một giao tiếp là public interface InterfaceName extends SuperInterfaces { //Thân giao tiếp } Hai thành phần bắt buộc trong một khai báo giao tiếp là-từ khóa interface và tên của giao tiếp. Từ khóa bổ trợ truy xuất là public chỉ ra rằng giao tiếp có thể được sử dụng bởi bất kỳ lớp nào bất kỳ gói nào. Nếu không xác định giao tiếp là public thì giao tiếp sẽ chỉ có thể truy xuất bởi các lớp được định nghĩa trong cùng gói với giao tiếp. Một khai báo giao tiếp có thể có một thành phần khác: danh sách các giao tiếp cha. Một giao tiếp có thể thừa kế các giao tiếp khác, giống như một lớp có thể thừa kế hoặc là lớp của lớp khác. Danh sách các giao tiếp cha được phân cách bởi dấu phẩy. Thân giao tiếp Thân giao tiếp chứa các khai báo phương thức cho tất cả các phương thức có trong giao tiếp. Một khai báo phương thức trong một giao tiếp kết 61
- thúc bởi dấu chấm phẩy (;) vì một giao tiếp không cung cấp cách cài đặt cho các phương thức được khai báo trong nó. Một giao tiếp có thể chứa các khai báo hằng ngoài các khai báo phương thức. Các khai báo thành phần trong một giao tiếp không được phép sử dụng một số từ khóa bổ trợ như private, protected transient, volatile, hoặc synchronized trong các khai báo thành phần của một giao tiếp. Trong ví dụ sau ta sẽ tìm hiểu cách định nghĩa một giao tiếp và cách thực thi một giao tiếp trong. public interface CalculatorInterface { public double add(double x, double y); public double sub(double x, double y); public double mul(double x, double y); public double div(double x, double y); } Thực thi giao tiếp Một giao tiếp định nghĩa một tập hợp hợp các quy ước về hành vi. Một lớp thực thi một giao tiếp tuân theo những quy ước đã được khai báo trong giao tiếp đó. Để khai báo một lớp thực thi một giao tiếp, ta đưa vào mệnh đề implements trong khai báo lớp. Một lớp có thể thực thi nhiều giao tiếp (Java hỗ trợ đa thừa kế giao tiếp), vì vậy sau từ khóa implements là một danh sách các giao tiếp được thực thi bởi một lớp. Chú ý: Mệnh đề implements đứng sau mệnh đề extends nếu tồn tại mệnh đề extends. class CalculatorTest implements CalculatorInterface { public double add(double x, double y) { return x+y; } public double sub(double x, double y) { return x-y; } public double mul(double x, double y) { 62
- return x*y; } public double div(double x, double y) {return x/y; } public static void main(String[] args) throws Exception { CalculatorInterface cal=new CalculatorTest(); if(args.length!=2) { System.out.println("Cach chay chuong trinh: java CalculatorImpl so1 so2"); return; } else { double x,y,z; x=Double.parseDouble(args[0]); y=Double.parseDouble(args[1]); System.out.println(x+"+"+y+"="+cal.add(x,y)); System.out.println(x+"-"+y+"="+cal.sub(x,y)); System.out.println(x+"*"+y+"="+cal.mul(x,y)); System.out.println(x+"/"+y+"="+cal.div(x,y)); } } } Kết quả thực hiện chương trình là C:\MyJava>java CalculatorTest 12 3 12.0+3.0=15.0 63
- 12.0-3.0=9.0 12.0*3.0=36.0 12.0/3.0=4.0 Sử dụng giao tiếp như là một kiểu Khi ta định nghĩa một giao tiếp mới, ta có thể định nghĩa kiểu dữ liệu tham chiếu mới. Giao tiếp có thể được sử dụng khi khai báo một biến tham chiếu. Giả sử MyInterface là một giao tiếp thì ta có thể khai báo như sau: MyInterface mi; 2.7. Các gói và sử dụng gói trong Java Các gói có các thành phần là các lớp, các interface, và các gói con có liên quan với nhau. Việc tổ chức thành các gói có một số lợi ích sau đây: o Các gói cho phép ta tổ chức các lớp thành các đơn vị nhỏ hơn (như các thư mục), và giúp cho việc định vị và sử dụng các lớp tương ứng trở nên dễ dàng hơn. o Tránh được các vấn đề về xung đột tên. o Cho phép ta bảo vệ các lớp, dữ liệu và các phương thức theo một quy mô lớn hơn so với phạm vi lớp. o Các tên gói có thể được sử dụng để định danh các lớp của bạn. Truy xuất tới các thành phần của gói trong Java Để truy xuất tới thành phần của gói trong Java ta có thể sử dụng cú pháp sau: MyPackage.MyClass MyPackage là tên gói, MyClass là tên lớp nằm trong gói MyPackage. Khai báo các gói trong chương trình Để có thể sử dụng các thành phần của một gói trong chương trình Java, ta cần phải khai báo gói cụ thể chứa lớp đó: import ten_goi.*;// ten_goi: tên gói Với khai báo như trên, ta có thể truy xuất tới tất cả các lớp, các interface nằm trong gói đó. Để khai báo sử dụng một lớp cụ thể trong chương trình ta khai báo dòng lệnh sau: import ten_goi.ten_lop; // ten_lop: tên lớp Giả sử ta có gói MyPackge, bên trong gói MyPackage lại có một số gói con như SubPackage1, SubPackage2, ta có thể khai báo sử dụng các thành phần trong gói con SubPackage1 như sau: import MyPackage.SubPackage1.*; Cách tạo ra các gói trong Java 64
- Bước 1: Khai báo một gói trong Java Giả sử ta khai báo một gói có tên là mypackage, bên trong gói này có lớp Calculator. package mypackage; public class Calculator { public double cong(double a,double b) { return a+b; } public double nhan(double a, double b) { return a*b; } public double tru(double a,double b) { return a-b; } public double chia(double a,double b) throws Exception { return a/b; } } Bước 2: Biên dịch C:\>javac -d C:\MyJava Calculator.java Một vài điều cần lưu ý khi khai báo các thành viên của gói. Thứ nhất, các thành phần của gói cần được khai báo với thuộc tính public, nếu cần truy xuất chúng từ bên ngoài. 2.6. Quản lý ngoại lệ (Exception Handling) Khái niệm Trong quá trình xử lý, các ứng dụng có thể bất ngờ gặp các lỗi với các mức độ nghiêm trọng khác nhau. Khi một phương thức tác động trên một đối tượng, đối tượng có thể phát hiện các vấn đề trạng thái bên trong (chẳng hạn 65
- các giá trị không nhất quán, như lỗi chia 0), phát hiện các lỗi với các đối tượng hay dữ liệu mà nó thao tác (như file hay địa chỉ mạng) xác định nó vi phạm các qui tắc cơ bản (như đọc dữ liệu từ một luồng đã bị đóng), Rất nhiều người lập trình không thể kiểm tra tất cả các trạng thái lỗi có thể xảy ra. Exception cung cấp một cách để kiểm tra các lỗi mà không chia cắt mã. Exception cũng đưa ra một cơ chế báo lỗi một cách trực tiếp chứ không sử dụng các cờ hay các hiệu ứng phụ. Các ngoại lệ trong Java Trong Java có một lớp Exception, mọi lớp ngoại lệ là lớp con của lớp này. Lớp Exception là lớp con của lớp Throwable Throwable Exception Hình 2.7 Lớp Throwable chứa một xâu được sử dụng để mô tả ngoại lệ. Ngoại lệ được phân thành hai loại: Ngoại lệ được kiểm tra (checked exception) và ngoại lệ không được kiểm tra (unchecked exception). Ngoại lệ được kiểm tra là ngoại lệ mà trình biên dịch sẽ kiểm tra phương thức của người lập trình và chỉ đưa ra ngoại lệ khi chúng được thông báo để đưa ra. Ngoại lệ không được kiểm tra là lớp con của các lớp Error; RuntimeException. Java cung cấp một mô hình quản lý các ngoại lệ cho phép kiểm tra các lỗi ở các vị trí có liên quan. Khối try và catch 66
- Cú pháp o Khối try Bao gồm một tập hợp các lệnh có thể phát sinh ngoại lệ trong khi xử lý. Một phương thức, có thể đưa ra một ngoại lệ cũng được đặt try Các khối try lồng nhau try{ stmt1; stmt2; try{ stmt3; stmt4; } catch(Exception e) { } } catch(Exception e) { } Khi các khối try được lồng nhau, khối try bên trong được xử lý trước và một ngoại lệ được đưa ra trong khối đó được đón bắt trong các khối try catch con. Nếu khối catch bên trong không thỏa mãn thì các khối try bên ngoài được kiểm tra. Nếu một khối catch phù hợp được tìm thấy, thì ngoại lệ được quản lý trong khối đó ngược lại thì môi trường Java Runtime quản lý ngoại lệ. try { doFileProcessing(); displayResults(); } catch(Exception e) { System. er.println(e.getMessage()); } 67
- Bất kỳ lỗi nào xảy ra trong quá trình xử lý doFileProcessing() hay displayResult() thì sẽ đựơc đón bắt bởi khối catch và được xử lý. Nếu có lỗi xảy ra trong quá trình xử lý doFileProcessing(), phương thức displayResult() sẽ không bao giờ được gọi, và khối catch sẽ được xử lý. Một khối try có thể có nhiều khối catch và xử lý các kiểu khác nhau try { } catch(Exception e) { } catch(Exception e) { } finally { //Thực hiện công việc thu dọn } Ví dụ: class TryCatch { public static void main(String[] args) {int x,y; try{ x=Integer.parseInt(args[0]); y=Integer.parseInt(args[1]); x=x/y; System.out.println("x="+x); } catch(ArithmeticException e) { System.out.println("Khong the chia cho 0"); System.err.println(e); 68
- } } } Kết quả 1 C:\MyJava\Baitap>java TryCatch 18 9 x=2 Kết quả 2 C:\MyJava\Baitap>java TryCatch 9 0 Khong the chia cho 0 java.lang.ArithmeticException: / by zero Khối finally Khối finally là khối mà chúng ta thấy các lệnh trả về các tài nguyên cho hệ thống và các lệnh khác để in ra bất kỳ thông báo nào. Các lệnh trong khối finanally có thể là: o Đóng một file. o Đóng một resultset (Lập trình cơ sở dữ liệu). o Ngắt liên kết được thiết lập với cơ sở dữ liệu. Khối finally luôn được xử lý dù ngoại lệ có xảy ra hay không Mệnh đề throw Các ngoại lệ được đưa ra bằng cách sử dụng lệnh throw, nó nhận một đối tượng làm tham số, đối tượng thuộc lớp là lớp con của lớp Throwable Ví dụ: class ArraySizeException extends NegativeArraySizeException { ArraySizeException() { super("Nhap kich thuoc mang khong hop le"); } } class ThrowDemo 69
- { int size, a[]; ThrowDemo(int s) { size =s; try{ checkSize(); } catch(ArraySizeException e) { System.out.println(e); } } void checkSize() throws ArraySizeException { if(size java ThrowDemo -1 ArraySizeException: Nhap kich thuoc mang khong hop le Giải thích: Chúng ta đã tạo ra một lớp có tên ArraySizeException, lớp này là lớp con của lớp NegativeArraySizeException. Bằng cách tạo ra một đối tượng của lớp này, chúng ta đã in ra thông báo ngoại lệ. Phương thức checkSize() có thể đưa ra ngoại lệ ArraySizeException. 70
- try không có ngoại lệ có ngoại lệ finally catch finally Hình 2.8 Ví dụ: class FinallyDemo { String name; int x,y; FinallyDemo(String s[]) { try{ name = new String("try catch finally demo"); x = Integer.parseInt(s[0]); y=Integer.parseInt(s[1]); System.out.println(name); System.out.println("Ket qua "+x/y); } catch(ArithmeticException e) { System.err.println("Khong the chia 0!"); } finally 71
- { name = null; System.out.println("Xu ly khoi finally"); } } public static void main(String[] args) { new FinallyDemo(args); } } Kết quả 1 C:\MyJava\Baitap>java FinallyDemo 16 0 try catch finally demo Khong the chia 0! Xu ly khoi finally Kết quả 2 C:\MyJava\Baitap>java FinallyDemo 16 4 try catch finally demo Ket qua 4 Xu ly khoi finally Một số ngoại lệ thường gặp o RuntimeException o ArithmeticException o IllegalArgumentException o ArrayIndexOutOfBoundsException o NullPointerException o SecurityException o NoSuchElementException o ClassNotFoundException 72
- o AWTException o DataFormatException o SQLException o IOException o UnknownHostException o SocketException o EOFException o MalformedURLException o FileNotFoundException o IllegalAccessException o NoSuchMethodException 73
- Chương 3 Các luồng vào ra 1. Khái niệm về luồng trong Java Khi lập bất kỳ chương trình nào trong một ngôn ngữ nào thì vấn đề vào ra dữ liệu giữa chương trình và nguồn dữ liệu cũng như đích dữ liệu là vấn đề mà người lập trình cần phải quan tâm. Làm thế nào để ta có thể truyền dữ liệu cho một chương trình Java. Có hai cách hiệu quả để thực hiện điều này: Thông qua một tài nguyên tuần tự nào đó như file hoặc qua một máy tính khác. Thông qua giao diện người máy. Mục đích của chương này là xem xét cách truyền dữ liệu cho một chương trình thông qua một máy tính khác hay tập tin. 1.1. Khái niệm luồng (stream) Theo nghĩa đen luồng là một đường ống nước. Về mặt thuật ngữ chuyên ngành ta có thể hiểu “Các luồng là các dãy dữ liệu có sắp thứ tự”. Xét trên quan điểm của chương trình và nguồn dữ liệu (Data Soure) ta có thể phân loại luồng thành hai loại: Luồng xuất (output stream) và luồng nhập (input stream). Để trực quan hơn chúng ta xem hình vẽ dướ đây: InputStream Data Source Program OutputStream Hình 3.1 Như vậy nếu chúng ta cần lấy dữ liệu từ nguồn vào chương trình thì cần phải sử dụng luồng nhập. Ngược lại, nếu ta cần ghi dữ liệu từ chương trình ra nguồn dữ liệu thì ta cần phải sử dụng luồng xuất. 74
- Ta có thể thấy rằng có rất nhiều luồng dữ liệ, chẳng hạn như từ một tệp tin, từ các thiết bị xuất và nhập chuẩn, từ liên kết mạng. Như vậy một chương trình có thể truy xuất tới nhiiều nguồn dữ liệu. Console InputStream Thiết bị Chương trình ứng dụng Tệp tin OutputStream Mạng Hình 3.2 2. Luồng xuất nhập chuẩn System.out: Luồng xuất chuẩn thường được sử dụng để hiển thị kết quả đầu ra trên màn hình. System.in: Luồng nhập chuẩn thường đến từ bàn phím và được sử dụng để hiện các ký tự. System.err: Luồng lỗi chuẩn. Các luồng trên còn được gọi là các luồng hệ thống. Mặc dù các luồng này rất có ích khi lập trình nhưng chúng không đủ mạnh khi giải quyết các vấn đề vào ra quan trọng khác. Trong các mục tiếp theo ta sẽ tìm hiểu sâu một số luồng trong gói java.io 3. Luồnng nhị phân 3.1. Lớp InputStream Lớp trừu tượng InputStream khai báo các phương thức để đọc dữ liệu đầu vào từ một nguồn cụ thể. Lớp InputStream là lớp cơ sở của hầu hết các luồng nhập trong gói java.io, và nó hỗ trợ các phương thức sau: 75
- Các phương thức: public InpuStream() InputStream chỉ hỗ trợ constructor không tham số. public abstract int read() throws IOException Phương thức cơ bản của lớp InputStream là phương thức read(). Phương thức này đọc một byte dữ liệu từ luồng nhập và trả về một số kiểu nguyên int có giá trị nằm trong khoảng từ 0 đến 255. Giá trị trả về là -1 khi kết thúc luồng. Phương thức read() chờ và phong tỏa các đoạn mã sau nó cho tới khi một byte dữ liệu được đọc. Việc nhập và xuất diễn ra với tốc độ chậm, vì vậy nếu chương trình của ta thực hiện một công việc khác quan trọng thì tốt nhất là đặt các lệnh nhập xuất vào một tuyến đoạn riêng của nó. Phương thức read() là phương thức trừu tượng bởi vì các lớp con cần thay đổi để thích ích với môi trường cụ thể. public int read(byte[] b) throws IOException Phương thức này đọc một dãy các byte dữ liệu liên tục từ một nguồn của luồng nhập và lưu vào mảng b. public int read(byte[] b, int offs, int len) throws IOException Phương thức này đọc một dãy các byte dữ liệu và lưu vào mảng b, vị trí bắt đầu lưu dữ liệu là offs và lưu len byte dữ liệu public int available() throws IOException Phương thức này cho biết còn bao nhiêu byte dữ liệu trong luồng. public long skip(long count) throws IOException Phương thức skip(long count) bỏ qua long byte dữ liệu public synchronized void mark(int readLimit) Phương thức này được sử dụng để dánh dấu vị trí hiện thời trong luồng public void reset() throws IOException Phương thức này xác định lại vị trí luồng là vị trí đánh dấu lần gần đây nhất. public boolean markSupported() Phương thức này trả về giá trị true nếu luồng này hỗ trợ đánh dấu và false nếu nó không hỗ trợ đánh dấu. public void close() throws IOException Khi đã làm việc xong với một luồng, ta cần đóng lại luồng đó. Điều này cho phép hệ điều hành giải phóng các tài nguyên gắn với luồng. 3.2. Lớp OutputStream 76
- Lớp trừu tượng OutputStream khai báo các phương thức để ghi dữ liệu ra luồng. Chúng bao gồm các phương thức sau đây: public OuputStream() Phương thức OutputStream hỗ trợ constructor không tham số public abstract void write(int b)throws IOException Phương thức này ghi một byte không dấu có giá trị trong khoảng từ 0 đến 255. Nếu ta truyền vào một số có giá trị lớn hơn 255 hoặc nhỏ hơn 0, nó sẽ thực hiện phép tính b =b mod 256 trước khi ghi giá trị vào luồng. public void write(byte[] b)throws IOException Phương thức này ghi dữ liệu từ luồng vào toàn bộ mảng b. public void write(byte[] b, int off, int len) throws IOException Phương thức này chỉ ghi một đoạn con của mảng dữ liệu bắt đầu từ vị trí offs và tiếp tục cho tới khi ghi hết len byte. public void close() Phương thức này đóng một luồng. Phương thức này được gọi để giải phóng các tài nguyên gắn với luồng. public void flush() Các luồng xuất nhập khác được thừa kế từ các luồng trừu tượng InputStream và OutputStream. Đối với mỗi kiểu dữ liệu và nguồn dữ liệu chúng ta có thể có các kiểu luồng xuất và nhập riêng, chẳng hạn DataInputStream, DataOutputStream, FileInputStream, FileOutputStream, Sau đây chúng ta sẽ lần lượt xem xét từng kiểu luồng cụ thể. 3.3. Các luồng xuất nhập mảng byte Để xây dựng một xâu ký tự biểu diễn dữ liệu có thể đọc được hoặc giải mã dữ liệu, người ta xem các mảng byte như là nguồn của các luồng nhập hoặc đích của các luồng xuất. Các luồng byte cung cấp các khả năng này. ByteArrayInputStream 77
- Hình 3.3 3.3.1. Luồng nhập mảng byte Lớp ByteArrayInputStream sử dụng một mảng byte như là một nguồn dữ liệu đầu vào. Nó có hai constructor: public ByteArrayInputStream(byte[] buf) Tạo ra một đối tượng ByteArrayInputStream từ một mảng xác định. Mảng đầu vào được sử dụng một cách trực tiếp. Khi kết thúc buf nghĩa là kết thúc nhập từ luồng. public ByteArrayInputStream(byte[] buf, int offset, int length) Tạo ra một đối tượng ByteArrayInputStream từ một mảng xác định, chỉ sử dụng một phần của mảng buf từ buf[offset] đến buff[offset+length-1] hoặc kết thúc mảng. ByteArrayInputStream tạo ra một luồng nhập từ một vùng đệm trong bộ nhớ được biểu diễn bằng một mảng byte. Lớp này không hỗ trợ bất kỳ phương thức mới nào, nó nạp chồng các phương thức read(), skip(), available(), và reset() của lớp cha InputStream. Ví dụ: Tạo một mảng gồm 100 byte rồi gắn vào mảng này một luồng ByteArrayInputStream để lấy dữ liệu ra. import java.io.*; public class LuongNhapMang { public static void main(String[] args) { byte[] b = new byte[100]; 78
- for(byte i=0;i java LuongNhapMang 012345678910111213141516171819202122232425262728 29303132333435363738394041424344454647484950515253 54555657585960616263646566676869707172737475767778 798081828384858687888990919293949596979899 Chú ý: Mỗi lần đọc luồng bằng phương thức read(), một byte dữ liệu không còn trong luồng, nhưng vẫn tồn tại trong mảng. 3.3.1. Luồng nhập mảng byte ByteArrayOutputStream tạo ra một luồng xuất trên một mảng byte. Nó cũng cung cấp các khả năng bổ sung. Các constructor: public ByteArrayOutputStream() Tạo ra một đối tượng ByteArrayOutputStream với kích thước mặc định public ByteArrayOutputStream(int size) Tạo ra một đối tượng ByteArrayOutputStream với kích thước xác định ban đầu. Các phương thức mới của lớp ByteArrayOutputStream: public synchronized byte[] toByteArray(): Phương thức này trả về một bản sao dữ liệu của luồng và lưu dữ liệu vào một mảng và có thể sửa đổi dữ liệu trong mảng này mà không cần thay đổi các byte của luồng xuất. public size() 79
- Trả về kích thước hiện thời của vùng đệm public String toString(int hiByte) Tạo một đối tượng String mới từ nội dung của luồng xuất mảng byte public String toString() Phương thức chuyển đổi một luồng byte thành một đối tượng String Ví dụ: Viết chương trình tạo lập một luồng xuất mảng (ByteArrayOutputStream) 100 byte. Ghi vào luồng xuất mảng 100 phần tử từ 0 đến 99. Đổ dữ liệu từ luồng xuất mảng vào mảng b. In dữ liệu từ mảng b ra màn hình. import java.io.*; class LuongXuatMang { public static void main(String[] args) { try{ //Tao mot luong xuat mang 100 byte ByteArrayOutputStream os = new ByteArrayOutputStream(100); //Ghi du lieu vao luong for(byte i=0;i<100;i++) os.write(i); //Doc du lieu tu luong vao mang byte[] b = os.toByteArray(); for(byte i=0;i<100;i++) System.out.print(b[i]+" "); os.close(); } catch(IOException e) { System.err.println(e); } } } Kết quả thực hiện chương trình: 80
- C:\MyJava\Baitap>java LuongXuatMang 012345678910111213141516171819202122232425262728 29303132333435363738394041424344454647484950515253 54555657585960616263646566676869707172737475767778 798081828384858687888990919293949596979899 3.4. Luồng xuất nhập tập tin Phần lớn việc nhập và xuất dữ liệu trong các ứng dụng là đọc và ghi dữ liệu từ các tệp tin và ghi vào dữ liệu vào tệp tin. Hai luồng trong java.io thực hiện việc xuất nhập tệp tin là FileInputStream và FileOutputStream. Mỗi kiểu luồng có ba constructor. Một constructor nhận một đối tượng String làm tên của tệp tin. Một constructor nhận một đối tượng File để tham chiếu đến tệp tin. Một constructor nhận đối tượng FileDescriptor làm tham số. FileDescriptor biểu diễn một giá trị phụ thuộc vào hệ thống mô tả một tệp đang mở. Đối với luồng xuất nhập tập tin ta hình dung như sau: chương trình Java là nơi tiêu thụ dữ liệu, tập tin là nơi cung cấp dữ liệu. Để đọc dữ liệu từ tập tin vào bộ nhớ ta sử dụng luồng nhập tập tin FileInputStream. Để ghi dữ liệu từ bộ nhớ vào tập tin ta sử dụng luồng xuất tập tin FileOutputStream. FileInputStream FILE FileOutputStream Hình 4.5 Ví dụ import java.io.*; public class FileIOExam { 81