Academia.eduAcademia.edu
Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông CH NG 1 Tổng quan về lập trình truyền thông Mục đích Ch ng này nhằm cung cấp cho các bạn một cái nhìn tổng quan về các vấn đề có liên quan trong lập trình truyền thông Yêu cầu Sau khi hoàn tất ch ng này, bạn có thể: ƒ Giải thích đ ợc C chế giao tiếp liên quá trình (Inter-Process Communication ) là gì. ƒ Mô tả ch c năng, nhiệm vụ c a các tầng trong mô hình OSI. ƒ Định nghĩa về giao th c và biện luận đ ợc sự cần thiết c a giao th c trong truyền thông . ƒ Mô tả về bộ giao th c TCP/IP. ƒ Định nghĩa mô hình Client – Server. ƒ Phân biệt đ ợc 2 chế độ giao tiếp: Nghẽn và Không nghẽn. ƒ Phân biệt đ ợc các kiểu kiến trúc ch Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy ng trình. 1 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.1. C chế giao tiếp liên quá trình là gì ? Truyền thông là một khái niệm dùng để chỉ sự giao tiếp, trao đổi thông tin giữa hai hay nhiều thực thể trong một hệ th ng nào đó. Nếu hệ th ng mà chúng ta xem xét là xã hội loài ng i, thì truyền thông có thể là quá trình trao đổi thông tin giữa ng i với ng i trong cuộc s ng thông qua các ph ng tiện truyền tải thông tin khác nhau nh không khí (trong trò chuyện trực tiếp), hệ th ng điện thoại, sách, báo, các ph ng tiện nghe nhìn, mạng máy tính... Nếu hệ th ng mà chúng ta xem xét là một hệ th ng máy tính hay một hệ th ng mạng thì truyền thông có thể đ ợc phân thành hai m c: ƒ M c phần c ng: là sự giao tiếp, trao đổi thông tin giữa các bộ phận vật lý cấu thành nên hệ th ng máy tính nh CPU, bộ nhớ, thiết bị vào ra, card giao tiếp mạng, nh vào các ph ng tiện truyền thông nh hệ th ng BUS nội, hệ th ng BUS vào ra hay các dây cáp mạng . . . ƒ M c phần mềm: là sự giao tiếp, trao đổi thông tin giữa các thành phần bên trong c a một ch ng trình hay giữa các ch ng trình với nhau thông qua các c chế truyền thông đ ợc hỗ trợ b i các hệ điều hành, hệ điều hành mạng. Trong các hệ th ng máy tính đ n nhiệm (monotasking) cổ điển, ví dụ MS-DOS, tại một th i điểm chỉ cho phép tồn tại một quá trình. Việc giao tiếp, trao đổi thông tin chỉ diễn ra trong phạm vi c a một ch ng trình. Đó là sự giao tiếp giữa các th tục d ới hình th c chia sẻ các biến toàn cục, hay bằng cách truyền các tham s khi gọi hàm, th tục hay bằng giá trị trả về c a một hàm . . . Ng ợc lại, trong các hệ th ng đa nhiệm (multitasking) có nhiều quá trình tồn tại song song nhau, mỗi quá trình đ ợc thực hiện trong một không gian địa chỉ (Address space) riêng biệt. Việc giao tiếp giữa các quá trình mu n thực hiện đ ợc đòi h i phải có những tiện ích hỗ trợ b i hệ điều hành, hệ điều hành mạng. Các tiện ích này th ng đ ợc gọi với cái tên là C chế giao tiếp liên quá trình (IPC - Inter-Process Communication). 1.2. Phân loại c chế giao tiếp liên quá trình Các c chế giao tiếp liên quá trình đ ợc hỗ trợ b i các hệ điều hành đa nhiệm, hệ điều hành mạng đ ợc chia ra làm hai loại: ƒ Loại 1: C chế giao tiếp liên quá trình hỗ trợ giao tiếp giữa các quá trình trên cùng một máy tính. (Hình H1.1) Hình 1.1 - C chế giao tiếp liên quá trình loại 1 Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 2 Khoa Công Nghệ Thông Tin - Đại Học Cần Th • - Giáo Trình Lập Trình Truyền Thông Loại 2: C chế giao tiếp liên quá trình hỗ trợ giao tiếp giữa các quá trình nằm trên các máy tính khác nhau (Hình H1.2). Hình 1.2 - C chế giao tiếp liên quá trình loại 2 Trong c chế giao tiếp liên quá trình trên cùng một máy, dữ liệu trao đổi qua lại giữa các quá trình phải đi xuyên qua hạt nhân (kernel) c a hệ điều hành. Đó có thể là một vùng nhớ dùng chung cho các quá trình đã đ ợc qui định tr ớc b i hệ điều hành, hay một tập tin trên đĩa đ ợc quản lý b i hệ điều hành trong đó một quá trình sẽ ghi dữ liệu vào, quá trình khác đọc dữ liệu ra, . . . Trong c chế giao tiếp liên quá trình trên các máy tính khác nhau, dữ liệu trao đổi giữa các quá trình không những phải đi qua hạt nhân nh c chế giao tiếp liên quá trình trên một máy tính mà h n thế các hạt nhân c a các máy có liên quan phải hiểu nhau. Nói cách khác các hạt nhân phải thoả thuận tr ớc với nhau về các qui tắc trao đổi thông tin giữa chúng. Thông th ng ta gọi các qui tắc này là các giao th c (Protocol). 1.3. Mô hình tham khảo OSI Để dễ dàng cho việc n i kết và trao đổi thông tin giữa các máy tính với nhau, vào năm 1983, Tổ ch c tiêu chuẩn thế giới ISO đã phát triển một mô hình cho phép hai máy tính có thể g i và nhận dữ liệu cho nhau. Mô hình này dựa trên tiếp cận phân tầng (lớp), với mỗi tầng đảm nhiệm một s các ch c năng c bản nào đó và đ ợc gọi là mô hình OSI. Để hai máy tính có thể trao đổi thông tin đ ợc với nhau cần có rất nhiều vấn đề liên quan. Ví dụ nh cần có Card mạng, dây cáp mạng, điện thế tín hiệu trên cáp mạng, cách th c đóng gói dữ liệu, điều khiển lỗi đ ng truyền ... Bằng cách phân chia các ch c năng này vào những tầng riêng biệt nhau, việc viết các phần mềm để thực hiện chúng tr nên dễ dàng h n. Mô hình OSI giúp đồng nhất các hệ th ng máy tính khác biệt nhau khi chúng trao đổi thông tin. Mô hình này gồm có 7 tầng: 7. Tầng ng dụng (Application Layer) Đây là tầng trên cùng, cung cấp các ng dụng truy xuất đến các dịch vụ mạng. Nó bao gồm các ng dụng c a ng i dùng, ví dụ nh các Web Browser (Netscape Navigator, Internet Explorer ), các Mail User Agent (Outlook Express, Netscape Messenger, ...) hay các ch ng trình làm server cung cấp các dịch vụ mạng nh các Web Server (Netscape Enterprise, Internet Information Service, Apache, ...), Các FTP Server, các Mail server (Send mail, MDeamon). Ng i dùng mạng giao tiếp trực tiếp với tầng này. 6. Tầng trình bày (Presentation Layer) Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 3 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Tầng này đảm bảo các máy tính có kiểu định dạng dữ liệu khác nhau vẫn có thể trao đổi thông tin cho nhau. Thông th ng các máy tính sẽ th ng nhất với nhau về một kiểu định dạng dữ liệu trung gian để trao đổi thông tin giữa các máy tính. Một dữ liệu cần g i đi sẽ đ ợc tầng trình bày chuyển sang định dạng trung gian tr ớc khi nó đ ợc truyền lên mạng. Ng ợc lại, khi nhận dữ liệu từ mạng, tầng trình bày sẽ chuyển dữ liệu sang định dạng riêng c a nó. 5. Tầng giao dịch (Session Layer) Tầng này cho phép các ng dụng thiết lập, sử dụng và xóa các kênh giao tiếp giữa chúng (đ ợc gọi là giao dịch). Nó cung cấp c chế cho việc nhận biết tên và các ch c năng về bảo mật thông tin khi truyền qua mạng. 4. Tầng vận chuyển (Transport Layer) Tầng này đảm bảo truyền tải dữ liệu giữa các quá trình. Dữ liệu g i đi đ ợc đảm bảo không có lỗi, theo đúng trình tự, không bị mất mát, trùng lắp. Đ i với các gói tin có kích th ớc lớn, tầng này sẽ phân chia chúng thành các phần nh tr ớc khi g i đi, cũng nh tập hợp lại chúng khi nhận đ ợc. 3. Tầng mạng (Network Layer) Tầng này đảm bảo các gói dữ liệu (Packet) có thể truyền từ máy tính này đến máy tính kia cho dù không có đ ng truyền vật lý trực tiếp giữa chúng. Nó nhận nhiệm vụ tìm đ ng đi cho dữ liệu đến các đích khác nhau trong hệ th ng mạng. 2. Tầng liên kết dữ liệu (Data-Link Layer) Tầng này đảm bảo truyền tải các khung dữ liệu (Frame) giữa hai máy tính có đ ng truyền vật lý n i trực tiếp với nhau. Nó cài đặt c chế phát hiện và xử lý lỗi dữ liệu nhận. 1. Tầng vật ký (Physical Layer) Điều khiển việc truyền tải thật sự các bit trên đ ng truyền vật lý. Nó định nghĩa các tín hiệu điện, trạng thái đ ng truyền, ph ng pháp mã hóa dữ liệu, các loại đầu n i đ ợc sử dụng. Về nguyên tắc, tầng n c a một hệ th ng chỉ giao tiếp, trao đổi thông tin với tầng n c a hệ th ng khác. Mỗi tầng sẽ có các đ n vị truyền dữ liệu riêng: • • • • Tầng vật lý: bit Tầng liên kết dữ liệu: Frame Tầng mạng: Packet Tầng vận chuyển: Segment Trong thực tế, dữ liệu đ ợc g i đi từ tầng trên xu ng tầng d ới cho đến tầng thấp nhất c a máy tính g i. đó, dữ liệu sẽ đ ợc truyền đi trên đ ng truyền vật lý. Mỗi khi Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 4 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông dữ liệu đ ợc truyền xu ng tầng phía d ới thì nó bị "gói" lại trong đ n vị dữ liệu c a tầng d ới. Tại bên nhận, dữ liệu sẽ đ ợc truyền ng ợc lên các tầng cao dần. Mỗi lần qua một tầng, đ n vị dữ liệu t ng ng sẽ đ ợc “tháo” ra. Đ n vị dữ liệu c a mỗi tầng sẽ có một tiêu đề (header) riêng, đ ợc mô tả trong hình 1.3. OSI chỉ là mô hình tham khảo, mỗi nhà sản xuất khi phát minh ra hệ th ng mạng c a mình sẽ thực hiện các ch c năng từng tầng theo những cách th c riêng. Các cách th c này th ng đ ợc mô tả d ới dạng các chuẩn mạng hay các giao th c mạng. Nh vậy dẫn đến tr ng hợp cùng một ch c năng nh ng hai hệ th ng mạng khác nhau sẽ không t ng tác đ ợc với nhau. Hình 1.4 sẽ so sánh kiến trúc c a các hệ điều hành mạng thông dụng với mô hình OSI. Hình 1.3 - Xử lý dữ liệu qua các tầng Hình 1.4 - Kiến trúc c a một s hệ điều hành mạng thông dụng Để thực hiện các ch c năng mạng sẽ có các protocol riêng: tầng 3 và tầng 4 trong mô hình OSI, mỗi hệ th ng ƒ UNIX: Tầng 3 dùng giao th c IP, tầng 4 giao th c TCP/UDP ƒ Netware: Tầng 3 dùng giao th c IPX, tầng 4 giao th c SPX ƒ Windows NT: chỉ dùng 1 giao th c NETBEUI Nếu chỉ dừng lại đây thì các máy tính UNIX, Netware, NT sẽ không trao đổi thông tin đ ợc với nhau. Với sự lớn mạnh c a mạng Internet, các máy tính cài đặt các hệ điều hành khác nhau đòi h i phải giao tiếp đ ợc với nhau, t c phải sử dụng chung một giao th c. Đó chính là bộ giao th c TCP/IP, giao th c c a mạng Internet. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 5 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.4. Mạng TCP/IP Đây là kiến trúc c a mạng Internet, chỉ gồm 5 tầng nh hình vẽ d ới đây: Hình 1.5 - Kiến trúc mạng TCP/IP Ng i ta còn gọi mô hình này là mô hình OSI đ n giản. Các giao th c đ ợc sử dụng trên mỗi tầng đ ợc qui định nh sau: Hình 1.6 – Bộ giao th c TCP/IP Tầng 3 sử dụng giao th c IP, tầng 4 có thể sử dụng giao th c TCP kết hoặc UPD chế độ không n i kết. chế độ có n i Tầng 5 là tầng c a các ng dụng. Mỗi loại ng dụng phải định nghĩa một giao th c riêng để các thành phần trong ng dụng trao đổi thông tin qua lại với nhau. Một s ng dụng phổ biến đã tr thành chuẩn c a mạng Internet nh : • • • • ng dụng Web: Sử dụng giao th c HTTP để tải các trang web từ Web Server về Web Browser. ng dụng th điện tử: Sử dụng giao th c SMTP để chuyển tiếp mail g i đi đến Mail Server c a ng i nhận và dùng giao th c POP3 hoặc IMAP để nhận mail về cho ng i đọc. ng dụng truyền tải tập tin: Sử dụng giao th c FTP để tải (download) các tập tin từ các FTP Server xa về máy ng i dùng hay ng ợc lại. ..... Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 6 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Thông th ng các tầng 1,2,3 và 4 đ ợc phát triển b i các nhà sản xuất hệ điều hành, nhà sản xuất các thiết bị phần c ng mạng. Chúng đảm nhận nhiệm vụ truyền tải thông tin cho các quá trình trên tầng ng dụng. Chúng cài đặt các c chế giao tiếp liên quá trình để các quá trình trên tầng ng dụng có thể truy xuất đến dịch vụ truyền tải thông tin do chúng cung cấp. Trong khi đó, tầng 5 là n i các nhà sản xuất phần mềm khai thác để tạo ra các ng dụng giải quyết các vấn đề khác nhau c a cuộc s ng. Nó đ ợc xem nh là tầng xử lý thông tin. 1.5. Dịch vụ mạng Dịch vụ mạng (Net service) là một ch đó trên hệ th ng mạng. ng trình ng dụng thực hiện một tác vụ nào Ví dụ: • • • Dịch vụ in trên mạng cho phép nhiều máy tính cùng sử dụng một máy in. Dịch vụ tập tin trên mạng cho phép chia sẻ ch tính. ng trình, dữ liệu giữa các máy Dịch vụ web cung cấp các trang web cho các máy tính khác nhau Có nhiều mô hình khác nhau để xây dựng các dịch vụ mạng. Một trong những mô hình đ ợc sử dụng khá phổ biến là mô hình Client-Server. Đây là một mô hình c bản để xây dựng các dịch vụ mạng. 1.6. Mô hình Client – Server 1.6.1. Giới thiệu Trong mô hình này, ch • • ng trình ng dụng đ ợc chia thành 2 thành phần: Quá trình chuyên cung cấp một s phục vụ nào đó, chẳng hạn: phục vụ tập tin, phục vụ máy in, phục vụ th điện tử, phục vụ Web... Các quá trình này đ ợc gọi là các trình phục vụ hay Server. Một s quá trình khác có yêu cầu sử dụng các dịch vụ do các server cung cấp đ ợc gọi là các quá trình khách hàng hay Client. Việc giao tiếp giữa client và server đ ợc thực hiện d ới hình th c trao đổi các thông điệp (Message). Để đ ợc phục vụ, client sẽ g i một thông điệp yêu cầu (Request Message) mô tả về công việc mu n server thực hiện. Khi nhận đ ợc thông điệp yêu cầu, server tiến hành phân tích để xác định công việc cần phải thực thi. Nếu việc thực hiện yêu cầu này có sinh ra kết quả trả về, server sẽ g i nó cho client trong một thông điệp trả l i (Reply Message). Dạng th c (format) và ý nghĩa c a các thông điệp Hình 1.7 – Mô hình Client-Server Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 7 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông trao đổi giữa client và server đ ợc qui định rõ b i giao th c (protocol) c a ng dụng. 1.6.2. Ví dụ về dịch vụ Web. Dịch vụ web đ ợc tổ ch c theo mô hình Client -Server, trong đó: • • • • Web server sẵn sàng cung cấp các trang web đang đ ợc l u trữ trên đĩa c ng cục bộ c a mình. Web Client, còn gọi là các Browser, có nhu cầu nhận các trang web từ các Web Server HTTP là giao th c trao đổi thông tin qua lại giữa Web client và Web Server. Thông điệp yêu cầu là một chuỗi có dạng sau: Command URL • HTTP/Ver \n\n Thông điệp trả l i có dạng sau: <HEADER>\n\n <CONTENT> • Giả sử Client cần nhận trang Web địa chỉ http://www.cit.ctu.edu.vn/, nó sẽ g i đến Web Server có tên www.cit.ctu.edu.vn thông điệp yêu cầu sau: GET www.cit.ctu.edu.vn HTTP/1.1\n\n • Server sẽ g i về nội dung sau: HTTP/1.0 200 OK Date: Mon, 24 Nov 2003 02:43:46 GMT Server: Apache/1.3.23 (Unix) (Red-Hat/Linux) mod_ssl/2.8.7 OpenSSL/0.9.6b DAV/1 .0.3 PHP/4.1.2 mod_perl/1.26 Last-Modified: Tue, 01 Jul 2003 08:08:52 GMT ETag: "17f5d-2abb-3f014194" Accept-Ranges: bytes Content-Length: 10939 Content-Type: text/html X-Cache: HIT from proxy.cit.ctu.edu.vn Proxy-Connection: close <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <LINK href="favicon.ico" rel="SHORTCUT ICON"> ............................... Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 8 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.6.3. Các chế độ giao tiếp Quá trình giao tiếp giữa client và server có thể diễn ra theo hai chế độ là nghẽn (blocked) hay không nghẽn (Non blocked). 1.6.3.1. Chế độ nghẽn : Trong chế độ này, khi quá trình client hay server phát ra lệnh g i dữ liệu, (thông th ng bằng lệnh send) , sự thực thi c a nó sẽ bị tạm dừng cho đến khi quá trình nhận phát ra lệnh nhận s dữ liệu đó (th ng là lệnh receive). T ng tự cho tr ng hợp nhận dữ liệu, nếu quá trình nào đó, client hay server, phát ra lệnh nhận dữ liệu, mà th i điểm đó ch a có dữ liệu g i đến, sự thực thi c a nó cũng tạm dừng cho đến khi có dữ liệu g i đến. 1.6.3.2. Chế độ không nghẽn: Hình 1.8 - Chế độ giao tiếp nghẽn Trong chế độ này, khi quá trình client hay server phát ra lệnh g i dữ liệu, sự thực thi c a nó vẫn đ ợc tiếp tục mà không quan tâm đến việc có quá trình nào phát ra lệnh nhận s dữ liệu đó hay không. T ợng tự cho tr ng hợp nhận dữ liệu, khi quá trình phát ra lệnh nhận dữ liệu, nó sẽ nhận đ ợc s l ợng dữ liệu hiện có (bằng 0 nếu ch a có quá trình nào g i dữ liệu đến). Sự thực thi c a quá trình vẫn đ ợc tiếp tục. Trong thực tế cần chú ý đến chế độ giao tiếp nghẽn khi lập trình, vì nó có thể dẫn đến tr ng hợp ch ng trình bị "treo" do s lần g i và nhận giữ liệu không bằng nhau giữa hai bên giao tiếp. 1.7. Các kiểu kiến trúc ch Hình 1.9 - Chế độ giao tiếp không nghẽn ng trình m c luận lý, các ch c năng mà một ch thành một trong 3 loại sau: ng trình ng dụng thực hiện có thể xếp 1. Các ch c năng thực hiện việc t ng tác với ng i dùng nh tạo các giao diện nhập liệu hay in các báo biểu, thông báo ra màn hình. Các ch c năng này đ ợc gọi chung là Dịch vụ giao diện ng ời dùng (User Interface Service). Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 9 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 2. Các ch c năng tính toán các dữ liệu, xử lý thông tin theo những qui luật (rule), giải thuật đ ợc qui định b i vấn đề mà ng dụng giải quyết. Các ch c năng này đ ợc gọi chung là Dịch vụ nghiệp vụ (Business Rule Service). 3. Trong quá trình tính toán, ch ng trình ng dụng cần truy vấn đến các thông tin đã có đ ợc l u trên đĩa c ng hay trong các c sỡ dữ liệu. Cũng nh cần thiết phải l u lại các kết quả tính toán đ ợc để sử dụng về sau. Các ch c năng này đ ợc gọi chung là Dịch vụ l u trữ (Data Storage Service). m c vật lý, các ch c năng này có thể đ ợc cài đặt vào một hay nhiều tập tin thực thi hình thành các kiểu kiến trúc ch ng trình khác nhau. Cho đến th i điểm hiện nay, ng i ta chia kiến trúc c a ch ng trình thành 3 loại đ ợc trình bày tiếp theo sau. 1.7.1. Kiến trúc đ n tầng (Single-tier Architecture) Trong kiểu kiến trúc này, cả 3 thành phần c a ch ng trình ng dụng (User Interface, Business Rule, Data Storage) đều đ ợc tích hợp vào một tập tin thực thi. Ví dụ: BKAV, D2, Winword, . . . Các ng dụng kiểu này chỉ đ ợc thực thi trên một máy tính. User Interface Business Rule Data Storage • • Hình 1.10 - Kiến trúc ch ng trình đ n tầng u điểm: • Dễ dàng trong thiết kế cài đặt ng dụng kiểu này. Nh ợc điểm: • • • • B i vì cả 3 thành phần đ ợc cài vào một tập tin thực thi, nên việc sửa lỗi hay nâng cấp ch ng trình thì rất khó khăn. Toàn bộ ch ng trình phải biên dịch lại cho dù chỉ sửa đổi một lỗi rất nh trong một thành phần nào đó ( User Interface chẳng hạn). Việc bảo trì, nâng cấp ấn bản mới là một công việc cực kỳ nặng nề vì ta phải thực hiện việc cài đặt trên tất cả các máy tính. Trong kiểu này, mỗi máy tính duy trì một c s dữ liệu riêng cho nên rất khó trong việc trao đổi, tổng hợp dữ liệu. Máy tính phải đ mạnh để có thể thực hiện đồng th i cả 3 loại dịch vụ. 1.7.2. Kiến trúc hai tầng (Two - Tier Architecture) Kiến trúc này còn đ ợc biết đến với tên kiến trúc Client-Server. Kiến trúc này gồm 2 ch ng trình thực thi: ch ng trình Client và ch ng trình Server. Cả hai ch ng trình có thể đ ợc thực thi trên cùng một máy tính hay trên hai máy tính khác nhau. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 10 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Client và Server trao đổi thông tin với nhau d ới dạng các thông điệp (Message) . Thông điệp g i từ Client sang Server gọi là các thông điệp yêu cầu (Request Message) mô tả công việc mà phần Client mu n Server thực hiện. Hình 1.11 - Kiến trúc ch ng trình Client-Server Mỗi khi Server nhận đ ợc một thông điệp yêu cầu, Server sẽ phân tích yêu cầu, thực thi công việc theo yêu cầu và g i kết quả về client (nếu có) trong một thông điệp trả l i (Reply Message). Khi vận hành, một máy tính làm Server phục vụ cho nhiều máy tính Client. Mỗi một ng dụng Client-Server phải định nghĩa một Giao th c (Protocol) riêng cho sự trao đổi thông tin, ph i hợp công việc giữa Client và Server. Protocol qui định một s vấn đề c bản sau: • • • • Khuôn dạng loại thông điệp. S l ợng và ý nghĩa c a từng loại thông điệp. Cách th c bắt tay, đồng bộ hóa tiến trình truyền nhận giữa Client và Server. .... Thông th ng phần client đảm nhận các ch c năng về User Interface, nh tạo các form nhập liệu, các thông báo, các báo biểu giao tiếp với ng i dùng. Phần Server đảm nhận các ch c năng về Data Storage. Nh đó dễ dàng trong việc bảo trì, chia sẻ tổng hợp dữ liệu trong toàn bộ công ty hoặc tổ ch c. Các ch c năng về Business Rule có thể đ ợc cài đặt server tạo ra hai loại kiến trúc Client - Server là: o Fat Client o Fat Server. phần client hoặc phần 1.7.2.1. Loại Fat Client Trong loại này Business Rule đ ợc cài đặt bên phía Client. Phần Server ch yếu thực hiện ch c năng về truy vấn và l u trữ thông tin. Hình 1.12 - Kiến trúc ch ng trình Client – Server theo kiểu Fat Client u điểm Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 11 Khoa Công Nghệ Thông Tin - Đại Học Cần Th • - Giáo Trình Lập Trình Truyền Thông Tạo ra ít giao thông trên mạng nh dữ liệu tạm th i trong quá trình tính toán đ ợc l u tại Client. Nh ợc điểm • • Vì Business Rule đ ợc cài đặt trên phía Client, đòi h i máy tính thực thi phần Client phải đ mạnh, dẫn đến t n kém trong chi phí đầu t phần c ng cho các công ty xí nghiệp. Phải cài lại tất cả các máy tính Client khi nâng cấp ch ng trình. 1.7.2.2. Loại Fat Server Trong loại này, phần lớn các ch c năng về Business Rule đ ợc đặt phần Server. Phần Client chỉ thực hiện một s ch c năng nh c a Business Rule về kiểm tra tính hợp lệ c a dữ liệu nhập b i ng i dùng. Hình 1.13 - Kiến trúc ch ng trình Client – Server theo kiểu Fat Server u điểm • • Vì Business Rule đ ợc đặt phần Server, các máy tính Client không cần phải có cấu hình mạnh. Việc nâng cấp ch ng trình khi Business Rule thay đổi tr nên nhẹ nhàng h n vì chỉ phải cài đặt lại phần Server. Nh ợc điểm • • Tạo ra nhiều thông điệp trao đổi giữa Client và Server làm tăng giao thông trên mạng. Tăng tải trên máy Server vì nó phải đồng th i thực hiện các ch c năng c a Business Rule và Data Storage làm giảm hiệu năng c a ch ng trình. 1.7.3. Kiến trúc đa tầng (N-Tier Architecture) Đây là kiến trúc cho các ng dụng phân tán (Distributed Application). Thông th ng là kiến trúc 3 tầng. Ch ng trình ng dụng đ ợc tách thành 3 phần riêng biệt t ng ng cho 3 ch c năng User Interface, Business Rule và Data Storage. Vì các ch c năng thuộc về Business Rule đ ợc tách thành một phần riêng, nó có thể đ ợc thực thi trên một máy tính Server riêng giải quyết đ ợc hầu hết các nh ợc điểm mắc phải c a kiến trúc đ n tầng và kiến trúc hai tầng nói trên. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 12 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Hình 1.12 - Kiến trúc ch ng trình đa tầng Kiến trúc này đáp ng t t với những thay đổi về qui luật xử lý dữ liệu c a vấn đề mà ng dụng giải quyết. Việc thay đổi chỉ ảnh h ng trên tầng Business Rule mà không ảnh h ng đến hai tầng còn lại. Thông th ng, ng i ta gọi tên các thành phần trên là: Client – Application Server – Database Server 1.8. Bài tập 1.8.1. Bài tập bắt buộc Bài tập 1.1: Protocol HTTP Tìm đọc và viết một báo cáo không quá 10 trang về giao th c HTTP. Bài tập 1.2: Chat Protocol Tìm hiểu về dịch vụ Chat trên mạng Internet. Viết một bảng báo cáo không qua 10 trang trình bày 2 nội dung sau: • • Một bảng mô tả các ch c năng th ng đ ợc hỗ trợ trong một dịch vụ Chat. Xây dựng Chat Protocol riêng c a bạn trong đó mô tả: o Các ch c năng hỗ trợ b i Chat Server. o Khuôn dạng (Format) và các loại thông điệp (Message) hỗ trợ b i Protocol. o S đồ trạng thái hoạt động c a server và client (giải thuật). o Minh họa các kịch bản khác nhau cho từng ch c năng c a dịch vụ. 1.8.2. Bài tập gợi ý Bài tập 1.3: POP3 Protocol Tìm đọc và viết một báo cáo không quá 10 trang về giao th c POP3. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 13 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông CH NG 2 S l ợc về ngôn ngữ Java Mục đích Ch ng này nhằm giới thiệu s l ợc về ngôn ngữ java cho các sinh viên đã có kiến th c căn bản về Lập trình h ớng đ i t ợng với C++. Ch ng này sẽ không đề cập đến tất cả các vấn đề có trong Java mà chỉ giới thiệu những vấn đề c bản nhất về ngôn ngữ Java, đ để các học viên có thể đọc hiểu các ch ng trình minh họa và làm đ ợc các bài tập ng dung các ch ng sau. Yêu cầu Sau khi hoàn tất ch • • • • • • • • • • • • ng này, bạn có thể: Trình bày đ ợc những vấn đề tổng quan về ngôn ngữ Java nh : o Đặc điểm và khả năng c a ngôn ngữ Java. o Khái niệm máy ảo c a Java (JVM - Java Virtual Machine ). o Vai trò c a bộ phát triển ng dụng JDK (Java Developpment Kit). o Phân biệt đ ợc hai kiểu ch ng trình Applet và Application c a Java. o Các kiểu dữ liệu và các phép toán đ ợc hỗ trợ b i Java. Biên soạn, biên dịch và thực thi thành công ch ng trình HelloWorld . Sử dụng thành thạo các cấu trúc điều khiển d ới Java nh : if, switch, while, do-while, for. Biết cách nhận đ i s c a ch ng trình Java. Biết đổi chuỗi thành s trong Java. Sử dụng đ ợc c chế ngoại lệ c a Java. Biết định nghĩa lớp mới, sử dụng một lớp đã có c a Java. Giải thích đ ợc c chế vào ra với Stream trong Java. Sử dụng thành thạo các ph ng th c c a hai lớp InputStream và OutputStream. Có thể nhập / xuất chuỗi trên một InputStream / OutputStream. Giải thích đ ợc c chế luồng (Thread). Cài đặt đ ợc các luồng trong Java. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 14 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.1. Giới thiệu về ngôn ngữ Java 1.1.1. Lịch sử phát triển Năm 1990, Sun MicroSystems thực hiện dự án Green nhằm phát triển phần mềm trong các thiết bị dân dụng. James Gosling, chuyên gia lập trình đã tạo ra một ngôn ngữ lập trình mới có tên là Oak. Ngôn ngữ này có cú pháp gần gi ng nh C++ nh ng b qua các tính năng nguy hiểm c a C++ nh truy cập trực tiếp tài nguyên hệ th ng, con tr , định nghĩa chồng các tác tử… Khi ngôn ngữ Oak tr ng thành, WWW cũng đang vào th i kỳ phát triển mạnh mẽ, Sun cho rằng đây là một ngôn ngữ thích hợp cho Internet. Năm 1995, Oak đổi tên thành Java và sau đó đến 1996 Java đã đ ợc xem nh một chuẩn công nghiệp cho Internet. 1.1.2. Khả năng c a ngôn ngữ Java • • • • • • Là một ngôn ngữ bậc cao nh C, C++, Perl, SmallTalk,.. cho nên có thể đ ợc dùng để tạo ra các ng dụng để giải quyết các vấn đề về s , xử lý văn bản, tạo ra trò ch i, và nhiều th khác. Có các môi tr ng lập trình đồ họa nh Visual Java, Symantec Cafe, Jbuilder, Jcreator, ... Có khả năng truy cập dữ liệu từ xa thông qua cầu n i JDBC (Java DataBase Connectivity) Hỗ trợ các lớp hữu ích, tiện lợi trong lập trình các ng dụng mạng (Socket) cũng nh truy xuất Web. Hỗ trợ lập trình phân tán (Remote Method Invocation ) cho phép một ng dụng có thể đ ợc xử lý phân tán trên các máy tính khác nhau. Và luôn đ ợc bổ sung các tính năng cao cấp khác trong các phiên bản sau. 1.1.2. Những đặc điểm c a ngôn ngữ Java • • • • • • • Ngôn ngữ hoàn toàn h ớng đ i t ợng. Ngôn ngữ đa nền cho phép một ch ng trình có thể thực thi trên các hệ điều hành khác nhau (MS Windows, UNIX, Linux) mà không phải biên dịch lại ch ng trình. Ph ng châm c a java là "Viết một lần , Chạy trên nhiều nền" (Write Once, Run Anywhere). Ngôn ngữ đa luồng, cho phép trong một ch ng trình có thể có nhiều luồng điều khiển đ ợc thực thi song song nhau, rất hữu ích cho các xử lý song song. Ngôn ngữ phân tán, cho phép các đ i t ợng c a một ng dụng đ ợc phân b và thực thi trên các máy tính khác nhau. Ngôn ngữ động, cho phép mã lệnh c a một ch ng trình đ ợc tải từ một máy tính về máy c a ng i yêu cầu thực thi ch ng trình. Ngôn ngữ an toàn, tất cả các thao tác truy xuất vào các thiết bị vào ra đều thực hiện trên máy ảo nh đó hạn chế các thao tác nguy hiểm cho máy tính thật. Ngôn ngữ đ n giản, dễ học, kiến trúc ch ng trình đ n giản, trong sáng. 1.1.3. Máy ảo Java (JMV - Java Virtual Machine) Để đảm bảo tính đa nền, Java sử dụng c chế Máy ảo c a Java. ByteCode đó là ngôn ngữ máy c a Máy ảo Java t ng tự nh các lệnh nhị phân c a các máy tính thực. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 15 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Một ch ng trình sau khi đ ợc viết bằng ngôn ngữ Java (có phần m rộng là .java) phải đ ợc biên dịch thành tập tin thực thi đ ợc trên máy ảo Java (có phần m rộng là .class). Tập tin thực thi này ch a các chỉ thị d ới dạng mã Bytecode mà máy ảo Java hiểu đ ợc phải làm gì. Khi thực hiện một ch ng trình, máy ảo Java lần l ợt thông dịch các chỉ thị d ới dạng Bytecode thành các chỉ thị dạng nhị phân c a máy tính thực và thực thi thực sự chúng trên máy tính thực. Máy ảo thực tế đó là một ch ng trình thông dịch. Vì thế các hệ điều hành khác nhau sẽ có các máy ảo khác nhau. Để thực thi một ng dụng c a Java trên một hệ điều hành cụ thể, cần phải cài đặt máy ảo t ng ng cho hệ điều hành đó. 1.1.4. Hai kiểu ng dụng d ới ngôn ngữ java Khi bắt đầu thiết kế một ng dụng d ới ngôn ngữ Java, bạn phải chọn kiểu cho nó là Application hay Applet. • Applet: Là một ch ng trình ng dụng đ ợc nhúng vào các trang web. Mã c a ch ng trình đ ợc tải về máy ng i dùng từ Web server khi ng i dùng truy xuất đến trang web ch a nó. Application: Là một ch ng trình ng dụng đ ợc thực thi trực tiếp trên các máy ảo c a Java. • 1.1.5. Bộ phát triển ng dụng Java (JDK- Java Development Kit) JDK là một bộ công cụ cho phép ng i lập trình phát triển và triển khai các ng dụng bằng ngôn ngữ java đ ợc cung cấp miễn phí b i công ty JavaSoft (hoặc Sun). Có các bộ Jdk cho các hệ điều hành khác nhau. Các ấn bản c a JDK không ngừng đ ợc phát hành, các bạn có thể tải về từ địa chỉ http://java.sun.com hoặc http://www.javasoft.com Bộ công cụ này gồm các ch ng trình thực thi đáng chú ý sau: • javac: Ch ng trình biên dịch các ch ng trình nguồn viết bằng ngôn ngữ java ra các tập tin thực thi đ ợc trên máy ảo Java. • java: Đây là ch ng trình làm máy ảo c a Java, thông dịch mã Bytecode c a các ch ng trình kiểu application thành mã thực thi c a máy thực. • appletviewer: Bộ thông dịch, thực thi các ch ng trình kiểu applet. • javadoc: Tạo tài liệu về chú thích ch ng trình nguồn một cách tự động. • jdb: Trình g r i. • rmic: Tạo Stub cho ng dụng kiểu RMI. • rmiregistry: Phục vụ danh bạ (Name Server) trong hệ th ng RMI 1.1.6. Kiểu dữ liệu c bản d ới Java • Kiểu s Tên kiểu byte short int long float double Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy Kích th ớc 1 byte 2 bytes 4 bytes 8 bytes 4 bytes 8 bytes 16 Khoa Công Nghệ Thông Tin - Đại Học Cần Th • - Giáo Trình Lập Trình Truyền Thông Kiểu ký tự char Java dùng 2 bytes cho kiểu ký tự, theo chuẩn mã UNICODE ( 127 ký tự đầu t ng thích với mã ASCII). Do đó, ta sử dụng t ng tự nh bảng mã ASCII. • Kiểu chuỗi ký tự String Thực chất đây là một lớp nằm trong th viện chuẩn c a Java (Core API), java.lang.String • Kiểu luận lý boolean Nhận 2 giá trị là : true và false. • Kiểu mảng o o o Khai báo: ƒ int[] a ; float[] yt; String[] names; ƒ hoặc: int a[]; float yt[]; String names[];int maTran[][]; float bangDiem[][]; Kh i tạo: ƒ a = new int[3]; yt = new float[10]; names = new String[50]; maTran = int[10][10]; Sử dụng mảng: ƒ int i = a[0]; float f = yt[9]; String str = names[20]; int x = matran [2][5]; 1.1.7. Các phép toán c bản Các phép toán trong Java cũng t • • • • • ng tự nh trong C++. Phép toán s học: +, - , *, / , % , =,++ , -- , += , - = , *= , /= , %= Phép toán logic ==, !=, && , ||, ! ,> , < , >= , <= Phép toán trên bit : & , | , ^ , << , >> , ~ Phép toán điều kiện : ? : Cách chuyển đổi kiểu: (Kiểu Mới) 1.1.8. Qui cách đặt tên trong Java Tên hằng, tên biến, tên lớp, tên ph ng th c , ... đ ợc đặt tên theo qui tắc bắt buộc sau: • • • • Tên phân biệt giữa chữ hoa và chữ th ng. Dùng các chữ cái, ký tự s , ký tự _ và $. Không bắt đầu bằng ký tự s . Không có khoảng trắng trong tên. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 17 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Để ch ng trình nguồn dễ đọc, dễ theo dõi ng (không bắt buộc): • • • i ta còn sử dụng quy ớc đặt tên sau Tên lớp: o Các ký tự đầu tiên c a một từ đ ợc viết hoa, o Các ký tự còn lại viết th ng. o Ví dụ: lớp Nguoi, SinhVien, MonHoc, String, InputStream, OutputStream. . . Tên biến, tên hằng, tên ph ng th c: o Từ đầu tiên viết th ng. o Ký tự đầu tiên c a từ th hai tr đi đ ợc viết hoa. Ví dụ: ten, ngaySinh, diaChi, inTen(), inDiaChi(), getInputStream(), . . . Vị trí đặt dấu { và } để bắt đầu và kết thúc các kh i nh sau: if (condition) { command1; command1; } else { command3; command4; } 1.2. Ch ng trình ng dụng kiểu Application Java là một ngôn ngữ thuần đ i t ợng (pure object). Tất cả các thành phần đ ợc khai báo nh hằng, biến, hàm th tục đều phải nằm trong phạm vi c a một lớp nào đó. Một ng dụng trong Java là một tập hợp các lớp liên quan nhau, bao gồm các lớp trong th viện do Java cung cấp và các lớp đ ợc định nghĩa b i ng i lập trình. Trong một ng dụng chỉ có một Lớp thực thi đ ợc. Đây là lớp đầu tiên đ ợc xem xét đến khi chúng ta thực thi ng dụng. Lớp thực thi đ ợc này có các đặc điểm sau: • • • • Có tên lớp trùng với tên tập tin ch a nó. Phải khai báo phạm vi là public Có ch a ph ng th c: public static void main (String args[]){ ... } là ph ng th c đ ợc thực thi đầu tiên. Nếu nhiều lớp đ ợc định nghĩa trong một tập tin, chỉ có một lớp đ ợc khai báo public. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 18 Khoa Công Nghệ Thông Tin - Đại Học Cần Th 1.2.1. Ch - Giáo Trình Lập Trình Truyền Thông ng trình HelloWorld Trong ví dụ này, chúng ta viết một ch ng trình ng dụng in ra màn hình dòng chữ "Hello World !". Đây là ng dụng đ n giản chỉ có một lớp thực thi đ ợc tên là HelloWorld. Lớp này đ ợc khai báo là public, có ph ng th c main(), ch a trong tập tin cùng tên là HelloWorld.java (phần m rộng bắt buộc phải là .java). Ph ng th c System.out.print() sẽ in tất cả các tham s trong dấu () c a nó ra màn hình. Ta có thể dùng bất kỳ ch ng trình soạn thảo văn bản nào để biên soạn ch trình. Nh ng nhớ phải ghi lại với phần m rộng là .java. 1.2.3. Biên soạn ch ng ng trình bằng phần mềm Notepad c a Ms Windows Notepad là trình soạn thảo đ n giản có sẵn trong MS Windows mà ta có thể dùng để biên soạn ch ng trình HelloWorld. Hãy thực hiện các b ớc sau: • • Chạy ch ng trình Notepad: o Chọn menu Start \ Programs \ Accessories \ Notepad Nhập nội dung sau vào Notepad public class HelloWorld { public static void main(String args[]) { System.out.print("Hello World! \n"); } } • Save tập tin với tên HelloWorld.java o Chọn menu File \ Save o Tại cửa sổ Save As hãy nhập vào: ƒ Save in: Th mục n i sẽ l u tập tin ƒ File Name: HelloWorld.java ƒ Save as type: All Files ƒ Nhấp vào nút Save Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 19 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.2.4. Cài đặt bộ phát triển ng dụng JDK • • • • Chuẩn bị bộ nguồn cài đặt JDK phù hợp với hệ điều hành sử dụng (Giả sử Windows 2000) Chạy tập tin Setup.exe Chọn n i cài đặt, giả sử D:\jdk1.4 Đặt biến môi tr ng o PATH = D:\jdk1.4\bin; để có thể thực thi các ch ng trình này từ bất kỳ th mục hiện hành nào. o CLASSPATH = D:\jdk1.4\lib;.; chỉ đến các lớp th viện c a Java trong th mục D:\jdk1.4\lib và các lớp tại th mục hiện hành, thể hiện bằng dấu chấm( . ). 1.2.5. Biên dịch và thực thi ch • • • ng trình M cửa sổ MS-DOS: Chọn menu Start \ Programs \ Accessories \ Command Prompt. Chuyển vào th mục ch a tập tin HelloWorld.java Dùng ch ng trình javac để biên dịch tập tin HelloWorld.java javac HelloWorld.java Nếu có lỗi, trên màn hình sẽ xuất hiện thông báo lỗi với dấu ^ chỉ vị trí lỗi. o Nếu không có lỗi, tập tin thực thi HelloWorld.class đ ợc tạo ra. Thực thi ch ng trình HelloWorld.class o • java HelloWorld Trên màn hình sẽ xuất hiện dòng chữ Hello World! Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 20 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.2.6. Một s ví dụ 1.2.6.1. Hiển thị thông tin ra màn hành Để in thông tin ra màn hình bạn dùng ph ng th c System.out.print(arg1+ arg2+ .. + argn) Java sẽ tự động định dạng dữ liệu cho các tham s arg1, arg2, ..., argn tùy theo kiểu c a chúng. Hãy l u ch ng trình sau vào tập tin Display.java: public class Display { public static void main(String args[]) { int i = 10; String str = " nam yeu "; char ch = 'm'; System.out.print('\n'+ "Bai hat:" + i + str + ch); } } Biên dịch và thực thi ta có kết quả : Ph ng th c System.out.println(arg1+ arg2+ .. + argn) in các tham s và tự động xu ng dòng mới. 1.2.6.2. Đọc ký tự từ bàn phím Ph ng th c int System.int.read() trả một s nguyên là mã ASCII c a ký tự nhập từ bàn phím. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 21 Khoa Công Nghệ Thông Tin - Đại Học Cần Th Hãy l u ch - Giáo Trình Lập Trình Truyền Thông ng trình sau vào tập tin KeyRead.java import java.io.*; public class KeyRead { public static void main(String args[]) { try { int ch = System.in.read(); System.out.print("Ky tu " + (char)ch + " co ma ascii = "+ch); } catch(IOException ie) { System.out.print("Error " + ie) ; } } } Biên dịch và thực thi ta có kết quả : Trong ví dụ trên l u ý một s điểm sau: • • Dòng đầu tiên import java.io.*; là c chế để khai báo với trình biên dịch các lớp th viện c a Java mà ch ng trình có sử dụng đến. Trong tr ng hợp này ch ng trình khai báo sử dụng tất cả các lớp trong gói (package) java.io. Thực tế ch ng trình trên chỉ sử dụng lớp IOException c a gói java.io mà thôi, vì thế ta có thể thay thế dòng java.io.*; bằng java.io.IOException;. C chế ngoại lệ (Exception) c a java: try { .... } catch(IOException ie) { .... } sẽ đ ợc giải thích rõ phần sau. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 22 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.3. Các cấu trúc điều khiển trong Java 1.3.1. Lệnh if – else Cú pháp: if (Condition) { // Các lệnh sẽ đ ợc thực hiện nếu giá trị c a Condition là true } if (Condition) { // Các lệnh sẽ đ ợc thực hiện nếu giá trị c a Condition là true } else { // Các lệnh sẽ đ ợc thực hiện nếu giá trị c a Condition là false } Ví dụ: L u ch ng trình sau vào tập tin IfDemo.java : import java.io.*; public class IfDemo { public static void main(String args[]) { System.out.print("Vui long nhap mot ky tu:"); try { int ch = System.in.read(); if (ch == 'A') { System.out.print("Ban rat may man !"); } else { System.out.print("Ban khong gap may !"); } } catch(IOException ie) { System.out.print("Error:"+ie); } } } Biên dich và thực thi có kết quả nh sau: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 23 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.3.2. Phép toán ? Cú pháp: (condition) ? Operation1 : Operation2; Nếu điều kiện condition có giá trị là true lệnh sẽ trả về giá trị c a biểu th c Operation1, ng ợc lại sẽ trả về giá trị c a biểu th c Operation2. Ví dụ: L u ch ng trình sau vào tập tin QuestionOp.java : import java.io.*; public class QuestionOp { public static void main(String args[]) { System.out.print("Vui long nhap mot ky tu:"); try { int ch = System.in.read(); int point = (ch == 'A') ? 10:0; System.out.print("Diem cua ban la:"+point); } catch(IOException ie) { System.out.print("Error:"+ ie); } } } Biên dịch và thực thi đ ợc kết quả nh sau: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 24 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.3.3. Lệnh switch Cú pháp switch ( variable ) { case value1 : { Task 1; // Các tác vụ sẽ đ ợc thực thi nếu giá trị c a variable là value1 break; } case value2 : { Task 2; // Các tác vụ sẽ đ ợc thực thi nếu giá trị c a variable là value2 break; } ... default: Task n; // Tác vụ sẽ đ ợc thực thi nếu giá trị c a variable không là các giá trị trên } Ví dụ L u ch ng trình sau vào tập tin CaseOp.java import java.io.*; public class CaseOp { public static void main(String args[]) { System.out.print("Enter a number character: "); try { int ch = System.in.read(); switch(ch) { case '0': { System.out.print("Zero");break;} case '1': { System.out.print("One"); break;} case '2': { System.out.print("Two"); break;} case '3': { System.out.print("Three");break;} case '4': { System.out.print("Four"); break;} case '5': { System.out.print("Five"); break;} case '6': { System.out.print("Six"); break;} case '7': { System.out.print("Seven");break;} case '8': { System.out.print("Eight");break;} case '9': { System.out.print("Nine"); break;} default: { System.out.print("I don't know"); break;} } } catch(IOException ie) { System.out.print("Error "+ie); } } } Biên dịch và thực thi đ ợc kết quả sau: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 25 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.3.4. Lệnh while Cú pháp while (condition) { // nếu condition có giá trị là true, thì các tác vụ } đây sẽ đ ợc lặp lại Ví dụ L u ch ng trình sau vào tập tin WhileDemo.java import java.io.*; public class WhileDemo { public static void main(String args[]) { int num = '9'; while (num > '0') { System.out.print((char)num +" "); num--; } } } Biên dịch và thực thi đ ợc kết quả sau: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 26 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.3.5. Lệnh do - while Cú pháp do { // Lặp lại các tác vụ } while (condition) Ví dụ: L u ch đây cho đến khi điều kiện condition có giá trị là false ng trình sau vào tập tin DoWhileDemo.java import java.io.*; public class DoWhileDemo { public static void main(String args[]) { int num = '9'; do { System.out.print((char)num +" "); num--; } while (num > '0'); } } Biên dịch và thực thi đ ợc kết quả sau: 1.3.6. Lệnh for Cú pháp for (operation1; condition; operation2){ // Các tác vụ đ ợc lặp lại } T ng đ ng nh cấu trúc sau: operation1; while (condition) { // Các tác vụ đ ợc lặp lại operation2; } Ví dụ Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 27 Khoa Công Nghệ Thông Tin - Đại Học Cần Th L u ch - Giáo Trình Lập Trình Truyền Thông ng trình sau vào tập tin ForDemo.java import java.io.*; public class ForDemo { public static void main(String args[]) { for(int num = '9'; num>'0'; num --) { System.out.print((char)num +" "); } } } Biên dịch và thực thi đ ợc kết quả nh sau: 1.3.7. Lệnh break Vòng lặp c a các lệnh while, do-while và for sẽ kết thúc khi lệnh break đ ợc thực hiện. Ví dụ L u ch ng trình sau vào tập tin BreakDemo.java import java.io.*; public class BreakDemo { public static void main(String args[]){ int num =Integer.valueOf(args[0]).intValue(); int i= num / 2; while(true){ if (num % i ==0) break; i--; } System.out.println("So lon nhat chia het "+num+ " la: "+i); } } Biên dịch và thực thi đ ợc kết quả sau: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 28 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Ch ng trình trên đổi đ i s th nhất c a nó (l u trong args[0]) thành s ( bằng lệnh Integer.valueOf(args[0]).inValue() ) và tìm s lớn nhất chia hết s này. 1.3.8. Lệnh continue Trong một lần lặp nào đó c a các lệnh while, do-while và for, nếu gặp lệnh continue thì lần lặp sẽ kết thúc (b qua các lệnh phía sau continue) để bắt đầu lần lặp tiếp theo. Ví dụ: L u ch ng trình sau vào tập tin ContinueDemo.java import java.io.*; public class ContinueDemo{ public static void main(String args[]){ int num =Integer.valueOf(args[0]).intValue(); System.out.print("The odd numbers: "); for (int i =0; i< num; i++ ){ if (i % 2 ==0) continue; System.out.print(i+ " "); } } } Biên dịch và thực thi đ ợc kết quả sau: Ch ng trình này in ra tất cả các s lẻ nh h n s đ a vào từ đ i s . Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 29 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.3.9. Một s vấn đề khác 1.3.9.1. Đọc đ i s c a ch Khi thực thi ch ng trình ng trình ta có thể nhập vào các đ i s từ dòng lệnh theo cú pháp sau: java ClassName arg1 arg2 arg3 argn Các đ i s cách nhau khoảng trắng. Để đón nhận các đ i s này, ph bắt buộc phải khai báo một tham s kiểu mảng các chuỗi ng th c main public static void main(String args[ ] ) { … } Các đ i s i s lần l ợt đ ợc đặt vào các phần tử c a mảng này. S l ợng đ i s có thể xác định đ ợc bằng cách truy xuất thuộc tính args.length c a mảng. Ví dụ L u ch ng trình sau vào tập tin PrintArgs.java public class PrintArgs { public static void main (String args[]) { for (int i = 0; i < args.length; i++) { System.out.println(args[i]); } } } Biên dịch và thực thi ch ng trình đ ợc kết quả sau: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 30 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.3.9.2. Đổi chuỗi thành s L u ch ng trình sau vào tập tin StringToNumber.java public class StringToNumber{ public static void main (String args[]) { int i = Integer.valueOf( args[0]).intValue(); long l = Long.valueOf( args[1]).longValue(); float f = Float.valueOf( args[2]).floatValue(); System.out.println("Integer number = "+i ); System.out.println("Long number = "+l ); System.out.println("Float number = "+f ); } } Biên dịch và thực thi ch ng trình đ ợc kết quả sau: 1.4. Ngoại lệ (EXCEPTION) Trong ch ng trình, có một s các "thao tác không chắc chắn", ví dụ nh các thao tác vào/ra: đĩa mềm ch a sẵn sàng, máy in có lỗi, n i kết mạng không thực hiện đ ợc . . . sẽ dẫn đến lỗi thực thi ch ng trình. Java hạn chế các lỗi sinh ra từ "thao tác không chắc chắn" bằng c chế Ngoại lệ (Exception). Ngoại lệ t c là một sự kiện xảy ra ngoài dự tính c a ch ng trình nếu không xử lý sẽ làm cho ch ng trình chuyển sang trạng thái không còn kiểm soát đ ợc. Ví dụ điều gì sẽ xảy ra nếu ch ng trình truy xuất đến phần tử th 11 c a một mảng 10 phần tử ? Một s ngôn ngữ nh C, C++ sẽ không báo lỗi gì cả, ch ng trình vẫn tiếp tục vận hành nh ng kết quả thì không thể xác định đ ợc. Để hạn chế những lỗi nh thế, Java bắt buộc các lệnh có thể dẫn đến các ngoại lệ phải có các đoạn mã xử lý phòng h khi ngoại lệ xảy ra theo cú pháp sau: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 31 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông try { Các thao tác vào ra có thể sinh ra các ngoại lệ. } catch (KiểuNgoạiLệ_01 biến) { ứng xử khi ngoại lệ KiểuNgoaiLệ_01 sinh ra } catch (KiểuNgoạiLệ_02 biến) { ứng xử khi ngoại lệ KiểuNgoaiLệ_02 sinh ra }finally { Công việc luôn luôn được thực hiện } Trong c chế này, các lệnh có thể tạo ra ngoại lệ sẽ đ ợc đ a vào trong kh i bao bọc b i từ khóa try {}. Tiếp theo đó là một loạt các kh i catch{}. Một lệnh có thể sinh ra một hoặc nhiều loại ngoại lệ. ng với một loại ngoại lệ sẽ có một kh i catch{} để xử lý cho loại ngoại lệ đó. Tham s c a catch chỉ ra loại ngoại lệ mà nó có trách nhiệm xử lý. Khi thực thi ch ng trình, nếu một lệnh nào đó nằm trong kh i try{} tạo ra ngoại lệ, điều khiển sẽ đ ợc chuyển sang các lệnh nằm trong các kh i catch{} t ng ng với loại ngoại lệ đó. Các lệnh phía sau lệnh tạo ra ngoại lệ trong kh i try{} sẽ bị b qua. Các lệnh nằm trong kh i finally{} thì luôn luôn đ ợc thực hiện cho dù có xảy ra ngoại lệ hay là không. Kh i lệnh finally{} là tùy chọn có thể không cần. Ngoại lệ có loại bắt buộc phải xử lý, t c phải có try{}, có catch{} khi sử dụng lệnh đó. Ví dụ nh lệnh đọc từ bàn phím. Trình biên dịch c a java sẽ báo lỗi nếu chúng ta không xử lý chúng. Ng ợc lại, có loại ngoại lệ không bắt buộc phải xử lý, ví dụ nh truy xuất đến phần tử bên ngoài chỉ s mảng. ph Tra c u tài liệu đặc tả các API c a java để biết đ ợc các ngoại lệ tạo ra từ một ng th c. Ví dụ: L u ch ng trình sau vào tập tin ExceptionDemo.java : public class ExceptionDemo { public static void main(String[] args) { try { System.out.println("Hello " + args[0]); } catch (ArrayIndexOutOfBoundsException e){ System.out.println("Hello Whoever you are."); } finally { System.out.println("How are you?"); } } } Biên dịch và thực thi có kết quả nh sau: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 32 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Trong ch ng trình trên chúng ta dự định sẽ chào ng i đ ợc đ a vào từ đ i s th nhất c a ch ng tình (đ ợc ch a trong phần tử args[0]). Tuy nhiên nếu ng i dùng thực thi ch ng trình quên đ a vào đ i s , t c phần tử args[0] không tồn tại. Ngoại lệ báo hiệu truy xuất đến phần tử nằm ngoài mảng (ArrayIndexOutOfBoundsException) đ ợc quẳng ra (throw). Khi đó đoạn mã lệnh trong kh i catch có tham s là loại ngoại lệ ArrayIndexOutOfBoundsException sẽ đ ọc thực hiện. 1.5. Một s vấn đề liên quan đến lớp trong Java 1.5.1. Định nghĩa lớp mới Ngoài các lớp đ ợc định nghĩa sẵn trong th viện chuẩn c a java, các lập trình viên có thể định nghĩa thêm các lớp c a mình theo cú pháp sau: class ClassName { // Danh sách các thuộc tính thuộc lớp DataType01 attribute1, attribute2, . .; DataType02 attribute3, attribute4, . .; // Danh sách các ph ng th c thuộc lớp ClassName([DataType parameter, DataType parameter]) { // Constructor ... } void method01() { ... } DataType method02( . . .) { ... return xx; } } ClassName là tên lớp mới đang đ ợc định nghĩa. Tạo đ i t ợng tên obj thuộc lớp ClassName. ClassName obj = new ClassName(); Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 33 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Ví dụ: Định nghĩa một lớp có: • • • • • Tên là Person Hai thuộc tính là name và address Ph ng th c kh i tạo có hai tham s để gán giá trị kh i động cho hai thuộc tính. Ph ng th c void display() cho biết ng i đó tên là gì, địa chỉ đâu. Ph ng th c main() tạo ra một đ i t ợng tên là tom thuộc lớp Person L u ch ng trình sau vào tập tin Person.java public class Person{ String name; //Thuộc tính String address; //Thuộc tính Person(String n, String address) { // Ph ng th c kh i tạo name = n; this.address = address; } void display(){ // Hiển thị tên và địa chỉ System.out.print(name + " is at "+ address); } public static void main(String args[]){ Person tom = new Person("Tom","Disney Land"); // Tạo đ i t ợng tom.display(); // Gọi ph ng th c c a đ i t ợng } } Biên dịch và thực thi ta đ ợc kết quả: 1.5.2. Phạm vi nhìn thấy c a một lớp Một lớp đ ợc định nghĩa và cài đặt bên trong một tập tin. Một tập tin có thể ch a một hoặc nhiều lớp. Trong một tập tin, chỉ có một lớp đ ợc khai báo là public (phía tr ớc từ khóa class), các lớp còn lại phải là private (mặc nhiên). Một lớp đ ợc khai báo là public sẽ đ ợc nhìn thấy b i các lớp khác cùng tập tin hay khác tập tin với nó. Ng ợc lại các lớp private chỉ đ ợc nhìn thấy b i các lớp nằm cùng tập tin với nó mà thôi. Ví dụ: Trong ví dụ này, chúng ta tách ph ng th c main ra kh i lớp Person và đ a nó vào lớp mới MultiClass. L u hai lớp này vào trong cùng một tập tin tên là MultiClass.java, với lớp MultiClass đ ợc khai báo là public, lớp Person khai báo private. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 34 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông // Lớp có phạm vi public có thể tham khảo từ bên ngoài tập tin public class MultiClass { public static void main(String args[]){ Person tom = new Person("Tom","Disney Land"); tom.display(); } } // Lớp có phạm vi private chỉ có thể tham khảo b i các lớp nằm cùng tập tin class Person{ String name; String address; Person(String n, String address) { name = n; this.address = address; } void display(){ System.out.println(name + " is at "+ address); } } Biên dịch và thực thi ta đ ợc kết quả: 1.5.3. Tính thừa kế • • • Một lớp chỉ có thể có một lớp cha (thừa kế đ n). Lớp cha đ ợc tham khảo từ lớp con b i từ khóa super. Dùng từ khóa extends để khai báo thừa kế. Cú pháp: class A extends B { // Khai báo A thừa kế từ B ... } Ví dụ: Định nghĩa lớp Client có các đặc điểm sau: • • • • Thừa kế từ lớp Person. Có thêm thuộc tính: telephone và buy (l ợng hàng mua). Có ph ng th c kh i tạo. Định nghĩa lại ph ng th c void display() c a lớp cha. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 35 Khoa Công Nghệ Thông Tin - Đại Học Cần Th L u ch - Giáo Trình Lập Trình Truyền Thông ng trình sau vào tập tin Client.java public class Client extends Person{ int telephone; long buy; public Client(String n, String a, int t, long b) { super(n,a); telephone=t; buy=b; } public void display() { super.display(); System.out.println( ", Number of telephone:"+ telephone + ", buy: "+ buy ); } public static void main(String args[]){ Client tom = new Client("Tom","Disney Land",123456,1000); tom.display(); } } Biên dịch và thực thi ta đ ợc kết quả: 1.6. Vào / Ra với Stream Stream là một dòng liên tục, có th tự các bytes dữ liệu chảy giữa ch ng trình và các thiết bị ngoại vi. Nó là khái niệm trừu t ợng giúp giảm bớt các thao tác vào ra ph c tạp đ i với ng i lập trình. Nó cho phép n i kết nhiều loại thiết bị ngoại vi khác nhau với ch ng trình. Nếu dòng dữ liệu trong Stream có h ớng chảy từ thiết bị ngoại vi vào ch ng trình thì ta nói đây là Stream nhập (Input Stream), ng ợc lại là Stream xuất (Output Stream). Đ i với Java, các thiết bị chỉ nhập, nh bàn phím, sẽ có các Stream nhập n i với nó, các thiết bị chỉ xuất, nh màn hình, sẽ có các stream xuất n i với nó , các thiết bị vừa xuất, vừa nhập, nh đĩa từ, thì có cả stream nhập và xuất n i với nó. Để giao tiếp với các thiết bị ngoại vi, ch ng trình tr ớc tiên phải lấy đ ợc các stream nhập / xuất gắn với thiết bị ngoại vi này. Sau đó, ch ng trình có thể g i dữ liệu ra ngoại vi bằng thao tác ghi vào Stream xuất c a ngoại vi. Ng ợc lại, ch ng trình có thể nhận dữ liệu từ ngoại vi bằng thao tác đọc stream nhập c a ngoại vi đó. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 36 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Nh vậy, ch ng trình chỉ làm việc trên các stream nhập và stream xuất, mà không quan tâm đến đặc điểm riêng biệt c a thiết bị ngoại vi n i với Stream. Điều này giúp ch ng trình giao tiếp với hệ th ng mạng cũng dễ dàng nh giao tiếp với màn hình, bàn phím hay đĩa từ. Một điểm khác cần l u ý là stream bao gồm những bytes r i rạc. Những bytes này mô tả những dạng dữ liệu khác nhau. Ví dụ một s integer khi viết vào stream sẽ chuyển thành 4 bytes. Vì thế cần phải có các thao tác chuyển đổi dữ liệu nhận và g i giữa ch ng trình và stream. Java hỗ trợ hai các lớp stream c bản trong gói java.io là: • • java.io.InputStream: Stream nhập java.io.OutputStream: Stream xuất Ngoài ra còn có các lớp Stream thừa kế từ hai lớp trên nhằm mục đích cung cấp các tiện ích cho các loại thiết bị vào ra chuyên biệt nh : FileInputStream, FileOutputStream, PipedInputStream, PipedOutputStream, . . . 1.6.1. Lớp java.io.InputStream Là loại stream cho phép ch c bản sau: ng trình nhận dữ liệu từ ngoại vi. Có các ph ng th c int read() throws IOException : Đọc 1 byte từ Stream • • Return 0-255 : Mã ASCII c a byte nhận đ ợc từ ngoại vi -1 : Stream đã kết thúc, không còn dữ liệu. Đ i với Java, System.in là một InputStream n i kết với bàn phím đ ợc tạo sẵn b i hệ th ng. Ch ng trình có thể dùng InputStream này để nhận các ký tự nhập từ bàn phím. Ví dụ: Hãy l u ch ng trình sau vào tập tin InStream1.java import java.io.*; public class InStream1 { public static void main(String args[]) { InputStream is = System.in; // KeyBoard = System.in while (true) { try { int ch = is.read(); if (ch ==-1 || ch =='q') break; System.out.print((char)ch); } catch (IOException ie) { System.out.print("Error: "+ie); } } } } Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 37 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Biên dịch và thực thi ta đ ợc kết quả sau: Ví dụ trên chờ nhận các ký tự đ ợc nhập từ bàn phím. int read(byte b[]) throws IOException: Đọc tất cả các byte hiện có trong Stream vào mảng b. • • Return 0-255: S l ợng byte đọc đ ợc. -1 : Stream đã kết thúc, không còn dữ liệu. int read(byte b[], int offset, int len) Đọc len byte từ Stream hiện tại, l u vào trong mảng b bắt đầu từ vị trí offset • • Return: s l ợng byte đọc đ ợc. -1 : Stream đã kết thúc. Các ph ng th c trên khi thực thi sẽ bị nghẽn (block) cho đến khi có dữ liệu hoặc kết trúc Stream hay một ngoại lệ xuất hiện. int available() Trả về s l ợng byte hiện có trong Stream mà không làm nghẽn ch ng trình. Ví dụ: L u ch ng trình sau vào tập tin có tên InStream2.java import java.io.*; public class InStream2 { public static void main(String args[]) { InputStream is = System.in; // KeyBoard = System.in while (true) { try { int num = is.available(); if (num > 0){ byte[] b = new byte[num]; int result = is.read(b); if (result == -1) break; String s = new String(b); System.out.print(s); } else { Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 38 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông System.out.print('.'); } } catch (IOException ie) { System.out.print("Error: "+ie); } } } } Biên dịch và thực thi ta đ ợc kết quả sau: Điểm khác biệt trong ví dụ này là các ký tự ta nhập từ bàn phím sẽ không hiển thị t c thì trên màn hình. Chúng chỉ hiển thị sau khi chúng ta nhấn phím Enter. 1.6.2. Lớp java.io.OutputStream Là loại stream cho phép ch c bản sau: ng trình xuất dữ liệu ra ngoại vi. Có các ph ng th c void write(int b) throws IOException • • Viết byte b vào Stream hiện tại, Return : void void write (byte[] b) throws IOException • • Viết tất cả các phần tử c a mảng b vào Stream hiện tại Return : void void write (byte[] b, int offset, int len) throws IOException: • • Viết len phần tử trong mảng b vào Stream hiện tại, bắt đầu từ phần tử có chỉ s là offset c a mảng. Return : void Đ i với Java, System.out là một OutputStream n i kết với màn hình đ ợc tạo sẵn b i hệ th ng. Ch ng trình có thể dùng OutputStream này để g i các ký tự ra màn hình. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 39 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Ví dụ: Hãy l u ch ng trình sau vào tập tin OutStream1.java import java.io.*; public class OutStream1 { public static void main(String args[]) { OutputStream os = System.out; // Monitor = System.out try { String str = "The example of OutputStream"; byte b[] = str.getBytes(); // Đổi chuỗi thành mảng các bytes os.write(b); } catch (IOException ie) { System.out.print("Error: "+ie); } } } Biên dịch và thực thi ch ng trình ta đ ợc kết quả sau: 1.6.3. Nhập chuỗi từ một InputStream InputStream là Stream nhập gồm chuỗi các bytes. Nó chỉ cung cấp các ph ng th c cho việc đọc byte và mảng các bytes. Để có thể đọc đ ợc chuỗi từ một InputStream ta phải sử dụng thêm các lớp sau: • • Lớp java.io.InputStreamReader: Là cầu n i để chuyển InputStream dạng byte sang InputStream dạng các ký tự (Character). Lớp java.io.BufferedReader: Hỗ trợ việc đọc văn bản từ một InputStream dạng ký tự. Ph ng th c String readLine() throws IOException c a BufferedReader cho phép đọc dòng văn bản kế tiếp trong InputStream. Một dòng kết thúc b i cặp ký tự ‘\r’’\n’ hoặc kết thúc Stream. Return: Một chuỗi ký tự hoặc null. Giả sử is là một đ i t ợng thuộc lớp InputStream. Để đọc chuỗi từ is ta thực hiện các thao tác sau: 1. InputStreamReader isr = new InputStreamReader(is); Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 40 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 2. BufferedReader br = new BufferedReader (isr); 3. String str = br.readLine(); Ví dụ: Đọc chuỗi từ bàn phím L u ch ng trình sau vào tập tin ReadLine.java import java.io.*; public class ReadLine{ public static void main(String args[]) { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); while (true) { try { String line = br.readLine(); if (line == null ) break; System.out.print(line); } catch (IOException ie) { System.out.print("Error: "+ie); } } } } Biên dịch và thực thi ta có kết quả sau: 1.6.4. Xuất chuỗi ra một OutputStream OutputStream là Stream xuất gồm chuỗi các bytes. Nó chỉ cung cấp các ph ng th c cho việc viết byte và mảng các bytes. Để có thể g i đ ợc chuỗi ra một OutputStream ta phải sử dụng lớp java.io.PrintWriter. Giả sử: os là một OutputStream, str là chuỗi cần viết vào os. Ta thực hiện các thao tác sau: 1. 2. 3. 4. PrintWriter pw = new PrintWriter(os); pw.wirte(str); hoặc pw.println(str); // Nếu mu n có ký tự xu ng dòng flush() // Đẩy dữ liệu từ buffer ra ngoại vi Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 41 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Ví dụ: Viết chuỗi ra màn hình L u ch ng trình sau vào tập tin PrintString.java import java.io.*; public class PrintString { public static void main(String args[]) { OutputStream os = System.out; PrintWriter pw = new PrintWriter(os); pw.write("This is a string \r\n"); pw.println("This is a line"); pw.write("Bye! Bye!"); pw.flush(); } } Biên dịch và thực thi ta đ ợc: 1.7. Luồng (Thread) Luồng là một cách thông dụng để nâng cao năng lực xử lý c a các ng dụng nh vào c chế song song. Trong một hệ điều hành cổ điển, đ n vị c bản sử dụng CPU là một quá trình. Mỗi quá trình có một Thanh ghi bộ đếm ch ng trình (PC-Program Counter), Thanh ghi trạng thái (Status Register), ngăn xếp (Stack) và không gian địa chỉ riêng (Address Space). Ng ợc lại, trong một hệ điều hành có hỗ trợ tiện ích luồng, đ n vị c bản sử dụng CPU là một luồng. Trong những hệ điều hành này, một quá trình bao gồm một không gian địa chỉ và nhiều luồng điều khiển. Mỗi luồng có bộ đếm ch ng trình, trạng thái thanh ghi và ngăn xếp riêng. Nh ng tất cả các luồng c a một quá trình cùng chia sẻ nhau một không gian địa chỉ. Nh đó các luồng có thể sử dụng các biến toàn cục, chia sẻ các tài nguyên nh tập tin, hiệu báo một cách dễ dàng... Cách th c các luồng chia sẻ CPU cũng gi ng nh cách th c c a các quá trình. Một luồng cũng có những trạng thái: đang chạy (running), sẵn sàng (ready), nghẽn (blocked) và kết thúc (Dead). Một luồng thì đ ợc xem nh là một quá trình nhẹ. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 42 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Hình 2.1 Các trạng thái c a Luồng Nh vào luồng, ng đồng th i. i ta thiết kế các server có thể đáp ng nhiều yêu cầu một cách Hình 2.2 - Sử dụng luồng cho các server Trong mô hình này, Server có một Luồng phân phát (Dispatcher thread) và nhiều Luồng thực hiện (Worker thread). Luồng phân phát tiếp nhận các yêu cầu n i kết từ các Client, rồi chuyển chúng đến các luồng thực hiện còn rảnh để xử lý. Những luồng thực hiện hoạt động song song nhau và song song với cả luồng phân phát, nh đó, Server có thể phục vụ nhiều Client một cách đồng th i. 1.7.1. Các m c cài đặt luồng Nhìn từ góc độ hệ điều hành , Luồng có thể đ ợc cài đặt • • một trong hai m c: Trong không gian ng i dùng (user space) Trong không gian nhân (kernel mode): Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 43 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.7.1.1. Tiếp cận luồng ở m c ng ời dùng: Hình 2.3 - Kiến trúc luồng cài đặt m c ng i dùng Không gian ng i dùng bao gồm một hệ th ng runtime mà nó tập hợp những th tục quản lý luồng. Các luồng chạy trong không gian nằm bên trên hệ th ng runtime thì đ ợc quản lý b i hệ th ng này. Hệ th ng runtime cũng l u giữ một bảng tin trạng thái để theo dõi trạng thái hiện hành c a mỗi luồng. T ng ng với mỗi luồng sẽ có một mục từ trong bảng, bao gồm các thông tin về trạng thái, giá trị thanh ghi, độ u tiên và các thông tin khác về luồng Tiếp cận này có hai m c định th i biểu (Scheduling): bộ định th i biểu cho các quá trình nặng và bộ định th i biểu trong hệ th ng runtime. Bộ lập biểu c a hệ th ng runtime chia th i gian sử dụng CPU đ ợc cấp cho một quá trình thành những khoảng nh h n để cấp cho các luồng trong quá trình đó. Nh vậy việc kết thúc một luồng thì v ợt ra ngoài tầm kiểm soát c a kernel hệ th ng. 1.7.1.2. Tiếp cận luồng ở m c hạt nhân hệ điều hành Hình 2.4 - Kiến trúc luồng cài đặt m c hệ th ng Trong tiếp cận này không có hệ th ng runtime và các luồng thì đ ợc quản lý b i kernel c a hệ điều hành. Vì vậy, bảng thông tin trạng thái c a tất cả các luồng thì đ ợc l u trữ b i kernel. Tất cả những l i gọi mà nó làm nghẽn luồng sẽ đ ợc bẫy (TRAP) đến kernel. Khi một luồng bị nghẽn, kernel chọn luồng khác cho thực thi. Luồng đ ợc chọn có thể cùng một quá trình với luồng bị nghẽn hoặc thuộc một quá trình khác. Vì vậy sự tồn tại c a một luồng thì đ ợc biết b i kernel và chỉ có một m c lập biểu trong hệ th ng. 1.7.2. Luồng trong java Trong Java, luồng là 1 đ i t ợng thuộc lớp java.lang.Thread. Một ch ng trình trong java có thể cài đặt luồng bằng cách tạo ra một lớp con c a lớp java.lang.Thread. Lớp này có 3 ph • • • ng th c c bản để điều khiển luồng là: public native synchronized void start() public void run() public final void stop() Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 44 Khoa Công Nghệ Thông Tin - Đại Học Cần Th Ph - Giáo Trình Lập Trình Truyền Thông ng th c start() Chuẩn bị mọi th để thực hiện luồng. Ph ph ng th c run() Thực hiện công việc thực sự c a luồng, () sẽ đ ợc kích hoạt một cách tự động b i ng th c start(). Ph ng th c stop() Kết thúc luồng. Luồng sẽ "chết" khi tất cả các công việc trong ph hoặc khi ph ng th c stop() đ ợc kích hoạt. ng th c run() đ ợc thực hiện Ví dụ Ví dụ sau định nghĩa lớp MyThread là một Thread có: • • Các thuộc tính o name: tên c a thread o n: s lần thread xuất hiện ra màn hình Các ph ng th c: o MyThread(String name, int n): Là ph ng th c kh i tạo, có nhiệm vụ gán giá trị cho 2 thuộc tính và gọi ph ng th c start() để cho thread hoạt động (start() tự động gọi run()) o run() In n lần dòng thông báo ra màn hình rồi kết thúc thread. o main() Tạo ra 4 thread thuộc lớp MyThread lần l ợt có tên là Thread0, Thread1, Thread2, Thread3. Mỗi thread có 1000 lần xuất hiện ra màn hình. L u ch ng trình sau vào tập tin MyThread.java public class MyThread extends Thread{ String name; int n; MyThread(String name, int n){ this.name = name; this.n = n; System.out.println("Thread "+name+" has been created ....!"); start(); } public void run(){ for(int i=0; i< n; i++) { System.out.println("Hello, I'm "+ name); System.out.println(" I go to bed now, bye bye ... wow ... "); } } Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 45 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông public static void main(String args[]){ int n = 1000; int nt = 4 ; for (int i=0; i< nt; i++){ MyThread t = new MyThread("Thread"+i,n); } } } Biên dịch và thực thi ta có kết quả sau: Các Thread in ra màn hình theo th tự ta không thể xác định tr ớc đ ợc vì chúng đ ợc thực thi song song nhau. Để dừng tạm th i màn hình kết quả khi ch ng trình đang thực thi, ta nhấp chuột vào cửa s DOS mà ch ng trình đang chạy. Sau đó ta nhấn phín Enter để ch ng trình tiếp tục. Ngoài ra, lớp Thread còn có 1 s các ph Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy ng th c khác : 46 Khoa Công Nghệ Thông Tin - Đại Học Cần Th • • • • - Giáo Trình Lập Trình Truyền Thông public static void sleep(long milliseconds) throws InterruptedException: làm cho Thread bị nghẽn (Blocked) một khoảng th i gian mili giây xác định. public final void suspend(): Chuyển Thread từ trạng thái sẳn sàng sang trạng thái nghẽn. public final void resume(): Chuyển Thread từ trạng thái nghẽn sang trạng thái sẵn sàng. public final void yield() : Chuyển Thread từ trạng thái đang chạy sang trạng thái sẵn sàng. 1.7.2.1 Độ u tiên c a luồng Độ u tiên c a các luồng xác định m c độ u tiên trong việc phân ph i CPU giữa các luồng với nhau. Khi có nhiều luồng đang trạng thái "Ready", luồng có độ u tiên cao nhất sẽ đ ợc thực thi (chuyển đến trạng thái "running" ). Độ u tiên trong Java đ ợc định nghĩa bằng các hằng s nguyên theo th tự giảm dần nh sau: • • • Thread.MAX_PRIORITY Thread.NORM_PRIORITY Thread.MIN_PRIORITY Hai ph • • ng th c liên quan đến độ u tiên c a luồng là: setPriority( int x): Đặt độ u tiên c a luồng là x int getPriority( ): Trả về giá trị u tiên c a luồng Ví dụ: Trong ví dụ này chúng ta tạo ra 12 Thread thuộc lớp MyThread. Một mảng 3 phần tử tên prio ch a 3 độ u tiên từ cao nhất đến thấp nhất. Thread th i sẽ có độ u tiên vị trí i%3 trong mảng prio. Nh vậy các thread 0,3,6,9 có độ u tiên cao nhất, sau đó đến Thread 1,4,7,10 và cu i cùng là các thread 2,5,8,11. L u ch ng trình sau vào tập tin PriorityThread.java public class PriorityThread{ public static void main(String args[]){ int n = 1000; int nt = 12; int prio[]= { Thread.MAX_PRIORITY, Thread.NORM_PRIORITY, Thread.MIN_PRIORITY}; for (int i=0; i< nt; i++){ MyThread t = new MyThread("Thread"+i,n); t.setPriority(prio[i%3]); } } } Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 47 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Biên dịch và thực thi ta đ ợc kết quả nh sau: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 48 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Các Thread 0,3,9 có độ u tiên cao h n các Thread khác cho nên chúng đ ợc thực thi th ng xuyên h n. Các Thread 2,5,8,11 có độ u tiên thấp nhất nên chúng kết thúc sau cùng. 1.7.3. Đồng bộ hóa giữa các luồng Tất cả các luồng c a một quá trình thì đ ợc thực thi song song và độc lập nhau nh ng lại cùng chia sẻ nhau một không gian địa chỉ c a quá trình. Chính vì vậy có thể dẫn đến khả năng đụng độ trong việc cập nhật các dữ liệu dùng chung c a ch ng trình (biến, các tập tin đ ợc m ) khi một luồng ghi lên một dữ liệu trong khi một luồng khác đang đọc dữ liệu này. Trong tr ng hợp đó, cần phải sử dụng c chế đồng bộ hóa c a Java. Có nhiều m c đồng bộ hóa nh : trên một biến, trên một câu lệnh, trên một kh i lệnh hay trên một ph ng th c. 1.8. Bài tập áp dụng Ch đề 1: C bản về Java • • Mục đích: o Sinh viên làm quen với ngôn ngữ Java, viết 1 s ch bằng Java. o Thực tập cách nhập / xuất thông tin qua Java. o Thiết kế lớp đ n giản qua Java. Yêu cầu ng trình đ n giản Sinh viên thực hiện các bài tập sau o o o o o o o Bài 1 : Khảo sát cây th mục JDK trên hệ th ng máy tính đang thực tập. Đặt các biến môi tr ng PATH và CLASSPATH đến các vị trí thích hợp. Bài 2 : Viết ch ng trình thể hiện ra màn hình câu : " Hello Java" Bài 3 : Viết ch ng trình nhập vào 1 chuỗi ký tự. Đổi thành chữ Hoa và in ra màn hình. Bài 4 : Viết ch ng trình nhập vào 1 s nguyên. Kiểm tra xem s đó có phải là s nguyên t hay không và thông báo ra màn hình. Bài 5 : Viết ch ng trình giải ph ng trình bậc 2. Bài 6 : Viết ch ng trình tính tổng c a dãy s từ 1 đến n (Với n đ ợc nhập từ bàn phím). Bài 7 : Nhập vào 1 dãy s thực, tính tổng c a các s d ng trong dãy đó. Ch đề 2: Thiết kế lớp trong Java • • Mục đích: o Thiết kế lớp d ới Java. Yêu cầu Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 49 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Sinh viên thực hiện các bài tập sau o o Bài 1 : Thiết kế lớp Diem (Điểm trong không gian 2 chiều) gồm : ƒ Thành phần dữ liệu : x,y kiểu int. ƒ Các hàm thành viên gồm : các ph ng th c kh i tạo, ph ng th c gán tọa độ cho 1 điểm, ph ng th c nhập tọa độ cho 1 điểm, ph ng th c in ra màn hình tọa độ điểm theo dạng (x,y), ph ng th c tính khoảng cách từ điểm đó đến g c tọa độ. ƒ Viết hàm main() khai thác lớp vừa định nghĩa. Bài 2 : Thiết kế lớp PhanSo ( Phân s ) có: ƒ 2 thuộc tính tử s và mẫu s thuộc kiểu s nguyên ƒ Các ph ng th c: Ph ng th c kh i tạo, ph ng th c in phân s , ph ng th c nghịch đảo phân s , ph ng th c trả về giá trị thực c a phân s , hàm cộng, trừ, nhân, chia 2 phân s . ƒ Ph ng th c main() sử dụng lớp PhanSo. Ch đề 3: Thread • • Mục đích: o Tìm hiểu về luồng (Thread), cách lập trình luồng, lập trình song song. Yêu cầu: Sinh viên thực bài tập sau: o Bài 1 : Viết ch ng trình mô ph ng bài toán "Ng i sản xuất - Ng i tiêu dùng", trong đó Ng i sản xuất sẽ sản xuất ra một s l ợng ngẫu nhiên n sản phẩm nào đó rồi yêu cầu nhập kho. Ng i tiêu dùng sẽ yêu cầu xuất kho một s l ợng ngẫu nhiên m sản phẩm nào đó từ kho. Yêu cầu nhập kho chỉ đ ợc chấp nhận nếu s l ợng hàng hóa đ a vào không v ợt quá s c ch a c a kho, nếu không, phải ch cho đến khi có đ chổ tr ng trong kho. Yêu cầu xuất kho chỉ đ ợc chấp nhận khi còn đ hàng trong kho nếu không cũng phải ch . Gợi ý : Thiết kế các lớp sau: ƒ ƒ ƒ ƒ Lớp Kho: Có thuộc tính là s c ch a, ph ng th c kh i tạo gán giá trị cho s c ch a, các ph ng th c xem s l ợng hàng tồn, ph ng th c nhập kho, ph ng th c xuất kho. In thông báo mỗi khi nhập kho hay xuất kho thành công Lớp Ng i Sản Xuất là một Thread: Có thuộc tính là kho để nhập hàng. Ph ng th c kh i tạo gán giá trị cho kho nhập hàng. Ph ng th c sản xuất lặp lại công việc là tạo ra n sản phẩm ngẫu nhiên và ch để nhập vào kho. Lớp Ng i Tiêu Dùng là một Thread: Có thuộc tính là kho để xuất hàng. Ph ng th c kh i tạo gán giá trị cho kho để xuất hàng. Ph ng th c tiêu dùng lặp lại công việc là ch để yêu cầu xuất m sản phẩm từ kho. Lớp Demo tạo ra một kho và 2 ng i sản xuất, 2 ng i tiêu dùng thực hiện việc nhập xuất trên cùng một kho. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 50 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông CH NG 3 ng dẫn (Pipe) Mục đích Ch ng này nhằm giới thiệu c chế giao tiếp liên quá trình đầu tiên là Pipe và cách sử dụng nó trong Java để làm ph ng tiện giao tiếp giữa các Thread trong một ch ng trình. Yêu cầu Sau khi hoàn tất ch • • • • ng này, bạn có thể: Trình bày đ ợc các đặc điểm c a Pipe. Biết cách tạo Pipe và xuất/ nhập dữ liệu trên Pipe trong Java. Giải thích đ ợc ch c năng c a dịch vụ phản hồi thông tin (Echo Service). Xây dựng, biên dịch và thực thi thành công ch ng trình PipedEcho. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 51 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.1. Giới thiệu về ng dẫn Ông dẫn là một tiện ích đ ợc hỗ trợ trong hầu hết các ngôn ngữ lập trình vận hành trên các hệ th ng đa nhiệm. ng dẫn cho phép hai quá trình nằm trên cùng một máy có thể trao đổi dữ liệu với nhau. Dữ liệu đi trên ng dẫn theo một chiều nhất định. Khi sử dụng ng dẫn, ng dùng một đầu cho việc viết dữ liệu vào và một đầu còn lại cho việc đọc dữ liệu ra. i ta Hình 3.1 Mô hình ng dẫn ng dẫn thích hợp cho tr vào cho quá trình kia. ng hợp dữ liệu tạo ra c a quá trình này sẽ là dữ liệu đầu Tuy nhiên ta cũng có thể sử dụng ng dẫn để xây dựng các ng dụng theo kiến trúc Client- Server bằng cách sử dụng hai ng dẫn: một ng dẫn để truyền các yêu cầu (request), một ng dẫn để truyền các trả l i (reply). Hình 3.2 – Dùng ng dẫn trong ch ng trình Client -Server Có hai loại ng dẫn: • • 1.2. ng dẫn bình th ng ( Normal Pipe): Giới hạn trong phạm vi không gian địa chỉ c a một quá trình mà thôi. Nó chỉ cho phép giao tiếp giữa quá trình cha với các quá trình con hay giữa các quá trình con c a một quá trình với nhau. Java hỗ trợ ng dẫn loại này. Trong đó các quá trình con đ ợc thay thế b i các luồng. ng dẫn có tên (Named Pipe): Loại này có thể cho phép hai quá trình có không gian địa chỉ khác nhau (trên cùng một máy) giao tiếp với nhau. Thực chất nó gi ng nh một tập tin với qui định rằng dữ liệu sẽ đ ợc lấy ra đầu tập tin và đ ợc thêm vào cu i tập tin. ng dẫn trong Java 1.2.1. Giới thiệu Java hỗ trợ tiên ích ng dẫn thông qua hai lớp java.io.PipedInputStream và java.io.PipedOutputStream. Chúng là hai đầu c a một ng dẫn. Trong đó PipedInputStream là đầu đọc dữ liệu và PipedOutputStream là đầu ghi dữ liệu c a ng dẫn. PipedInputStream là lớp con c a InputStream nên nó có tất cả các thuộc tính c a InputStream. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 52 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông PipedOutputStream là lớp con c a OutputStream nên nó có tất cả các thuộc tính c a OutputStream 1.2.2. Các cách tạo ng dẫn Để tạo một ng dẫn ta chỉ cần tạo ra hai đ i t ợng thuộc lớp PipedInputStream và PipedOutputStream và n i chúng lại với nhau. Khi đó dữ liệu đ ợc ghi vào PipedOutputStream sẽ đ ợc đọc ra đầu PipedInputStream: Hình 3.4 - Tạo ng dẫn trong Java Cách 1 1. Tạo đầu đọc: o PipedInputStream readId = new PipedInputStream(); 2. Tạo đầu ghi: o PipedOutputStream writeId = new PipedOutputStream(); 3. N i đầu đọc với đầu ghi hay ng ợc lại o readId.connect(writeId); o // hoặc writeId.connect(readId); Cách 2 1. Tạo đầu đọc: o PipedInputStream readId = new PipedInputStream(); 2. Tạo đầu ghi và n i vào đầu đọc đã có: o PipedOutputStream writeId = new PipedOutputStream(readId); Hoặc: Ta có thể tạo đầu ghi tr ớc rồi tạo đầu đọc sau. L u ý: Các ph ng th c kh i tạo c a PipedInputStream và PipedOutputStream sử dụng trên đòi h i phải "bắt" (catch) IOException do chúng có thể “quẳng” ra (throws).. 1.3. Dịch vụ phản hồi thông tin (Echo Service) Dịch vụ phản hồi thông tin là một dịch vụ tồn tại trên hệ th ng mạng UNIX. Dịch vụ này đ ợc xây dựng theo mô hình Client - Server, c chế hoạt động nh sau: • • Phần Server: Ch nhận các byte g i đến từ Client. Với mỗi byte nhận đ ợc, Server sẽ g i về đúng byte đã nhận tr về Client. Phần Client: G i các byte sang Server, ch nhận các byte g i về từ Server. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 53 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.4. Giả lập dịch vụ phản hồi thông tin bằng Pipe Phần kế tiếp ta xây dựng một ng dụng có tên là PipeEcho mô ph ng dịch vụ phản hồi thông tin để minh họa cách sử dụng Pipe làm ph ng tiện giao tiếp giữa các Thread trong một ng dụng. Hình 3.5 – Mô hình ng dụng PipeEcho Trong ng dụng này Client và Server là hai Thread thuộc lớp PipedEchoClient và PipedEchoServer. Việc trao đổi thông tin giữa client và server đ ợc thực hiện thông qua 2 Pipe (cwPipe-srPipe) và (swPipe-crPipe). PipedEchoClient nhận các ký tự từ bàn phím, g i chúng sang PipedEchoServer và ch nhận các ký tự g i về từ PipedEchoServer để in ra màn hình. PipedEchoServer ch nhận từng ký tự từ PipedEchoClient, đổi ký tự nhận đ ợc thành ký tự hoa và g i ng ợc về PipedEchoClient. 1.4.1. Lớp PipedEchoServer Hãy l u ch ng trình sau vào tập tin PipedEchoServer.java import java.io.*; public class PipedEchoServer extends Thread { PipedInputStream readPipe; PipedOutputStream writePipe; PipedEchoServer(PipedInputStream readPipe, PipedOutputStream writePipe){ this.readPipe = readPipe; this.writePipe = writePipe; System.out.println("Server is starting . . ."); start(); } public void run(){ while(true) { try{ int ch = readPipe.read(); ch = Character.toUpperCase((char)ch); writePipe.write(ch); Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 54 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông } catch (IOException ie) { System.out.println("Echo Server Error: "+ie ); } } } } 1.4.2. Lớp PipedEchoClient Hãy l u ch ng trình sau vào tập tin PipedEchoClient.java import java.io.*; public class PipedEchoClient extends Thread { PipedInputStream readPipe; PipedOutputStream writePipe; PipedEchoClient(PipedInputStream readPipe, PipedOutputStream writePipe){ this.readPipe = readPipe; this.writePipe = writePipe; System.out.println("Client creation"); start(); } public void run(){ while(true) { try { int ch=System.in.read(); writePipe.write(ch); ch = readPipe.read(); System.out.print((char)ch); } catch(IOException ie){ System.out.println("Echo Client Error: "+ie ); } } } } 1.4.3. Lớp PipedEcho Hãy l u ch ng trình sau vào tập tin PipedEcho.java import java.io.*; public class PipedEcho { public static void main(String argv[]){ try{ PipedOutputStream cwPipe = new PipedOutputStream(); PipedInputStream crPipe = new PipedInputStream(); PipedOutputStream swPipe = new PipedOutputStream(crPipe); PipedInputStream srPipe = new PipedInputStream(cwPipe); PipedEchoServer server = new PipedEchoServer(srPipe,swPipe); PipedEchoClient client = new PipedEchoClient(crPipe,cwPipe); } catch(IOException ie) { System.out.println("Pipe Echo Error:"+ie); } Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 55 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông } } 1.4.5. Biên dịch và thực thi ch Biên dịch và thực thi ch ng trình ng trình theo cách sau: Nhập vào bàn phím chuỗi ký tự mà bạn mu n rồi nhấp phím Enter. Bạn sẽ thấy chuỗi ký tự in hoa c a chuỗi vừa nhập xuất hiện trên màn hình. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 56 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông CH NG 4 Socket Mục đích Ch ng này nhằm giới thiệu về cách th c xây dựng ng dụng Client-Server trên mạng TCP/IP theo cả hai chế độ Có n i kết (TCP) và Không n i kết (UDP). Yêu cầu Sau khi hoàn tất ch • • • • • • • • ng này, bạn có thể: Giải thích đ ợc Socket là gì, vai trò c a s hiệu cổng (Port) và địa chỉ IP trong c chế Socket. Phân biệt đ ợc sự khác biệt c a hai loại Protocol TCP và UDP. Trình bày đ ợc các b ớc xây dựng một ch ng trình Client-Server sử dụng Socket làm ph ng tiện giao tiếp trong cả hai chế độ: Có n i kết và không n i kết. Liệt kê các lớp hỗ trợ lập trình Socket c a Java. Xây dựng đ ợc các ch ng trình Client sử dụng Sokcet chế độ có n i kết bằng ngôn ngữ Java. Xây dựng đ ợc các ch ng trình Server sử dụng Sokcet chế độ có n i kết phục vụ tuần tự và phục vụ song song bằng ngôn ngữ Java. Xây dựng đ ợc các ch ng trình Client-Server sử dụng Sokcet chế độ không n i kết bằng ngôn ngữ Java. Tự xây dựng đ ợc các Protocol mới cho ng dụng c a mình. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 57 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.1. Giới thiệu về socket 1.1.1. Giới thiệu Socket là một giao diện lập trình ng dụng (API-Application Programming Interface). Nó đ ợc giới thiệu lần đầu tiên trong ấn bản UNIX - BSD 4.2. d ới dạng các hàm hệ th ng theo cú pháp ngôn ngữ C (socket(), bind(), connect(), send(), receive(), read(), write(), close() ,..). Ngày nay, Socket đ ợc hỗ trợ trong hầu hết các hệ điều hành nh MS Windows, Linux và đ ợc sử dụng trong nhiều ngôn ngữ lập trình khác nhau: nh C, C++, Java, Visual Basic, Visual C++, . . . Socket cho phép thiết lập các kênh giao tiếp mà hai đầu kênh đ ợc đánh dấu b i hai cổng (port). Thông qua các cổng này một quá trình có thể nhận và g i dữ liệu với các quá trình khác. Hình 4.1 – Mô hình Socket Có hai kiểu socket: 1. Socket kiểu AF_UNIX chỉ cho phép giao tiếp giữa các quá trình trong cùng một máy tính 2. Socket kiểu AF_INET cho phép giao tiếp giữa các quá trình trên những máy tính khác nhau trên mạng. 1.1.2. S hiệu cổng (Port Number) c a socket Để có thể thực hiện các cuộc giao tiếp, một trong hai quá trình phải công b s hiệu cổng c a socket mà mình sử dụng. Mỗi cổng giao tiếp thể hiện một địa chỉ xác định trong hệ th ng. Khi quá trình đ ợc gán một s hiệu cổng, nó có thể nhận dữ liệu g i đến cổng này từ các quá trình khác. Quá trình còn lại cũng đ ợc yêu cầu tạo ra một socket. Ngoài s hiệu cổng, hai bên giao tiếp còn phải biết địa chỉ IP c a nhau. Địa chỉ IP giúp phân biệt máy tính này với máy tính kia trên mạng TCP/IP. Trong khi s hiệu cổng dùng để phân biệt các quá trình khác nhau trên cùng một máy tính. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 58 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Hình 4.2 – Cổng trong Socket Trong hình trên, địa chỉ c a quá trình B1 đ ợc xác định bằng 2 thông tin: (Host B, Port B1): Địa chỉ máy tính có thể là địa chỉ IP dạng 203.162.36.149 hay là địa chỉ theo dạng tên miền nh www.cit.ctu.edu.vn S hiệu cổng gán cho Socket phải duy nhất trên phạm vi máy tính đó, có giá trị trong khoảng từ 0 đến 65535 (16 bits). Trong đó, các cổng từ 1 đến 1023 đ ợc gọi là cổng hệ th ng đ ợc dành riêng cho các quá trình c a hệ th ng. Các cổng mặc định c a 1 s dịch vụ mạng thông dụng: S hiệu cổng Quá trình hệ th ng 7 Dịch vụ Echo 21 Dịch vụ FTP 23 Dịch vụ Telnet 25 Dịch vụ E-mail (SMTP) 80 Dịch vụ Web (HTTP) 110 Dịch vụ E-mail (POP) Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 59 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.1.3. Các chế độ giao tiếp Xét kiến trúc c a hệ th ng mạng TCP/IP Hình 4.3 – Bộ giao th c TCP/IP Tầng vận chuyển giúp chuyển tiếp các thông điệp giữa các ch với nhau. Nó có thể hoạt động theo hai chế độ: • • ng trình ng dụng Giao tiếp có n i kết, nếu sử dụng giao th c TCP Hoặc giao tiếp không n i kết, nếu sử dụng giao th c UDP Socket là giao diện giữa ch ng trình ng dụng với tầng vận chuyển. Nó cho phép ta chọn giao th c sử dụng tầng vận chuyển là TCP hay UDP cho ch ng trình ng dụng c a mình. Bảng sau so sánh sự khác biệt giữa hai chế độ giao tiếp có n i kết và không n i kết: Chế độ có n i kết (TCP) • • • Tồn tại kênh giao tiếp ảo giữa hai bên giao tiếp Dữ liệu đ ợc g i đi theo chế độ bảo đảm: có kiểm tra lỗi. truyền lại gói tin lỗi hay mất, bảo đảm th tự đến c a các gói tin . . . Dữ liệu chính xác, T c độ truyền chậm. Chế độ không n i kết (UDP) • • • • Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy Không tồn tại kênh giao tiếp ảo giữa hai bên giao tiếp Dữ liệu đ ợc g i đi theo chế độ không bảo đảm: Không kiểm tra lỗi, không phát hiện không truyền lại gói tin bị lỗi hay mất, không bảo đảm th tự đến c a các gói tin . . . Dữ liệu không chính xác, t c độ truyền nhanh. Thích hợp cho các ng dụng cần t c độ, không cần chính xác cao: truyền âm thanh, hình ảnh . . . 60 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.2. Xây dựng ng dụng Client-Server với Socket Socket là ph ng tiện hiệu quả để xây dựng các ng dụng theo kiến trúc ClientServer. Các ng dụng trên mạng Internet nh Web, Email, FTP là các ví dụ điển hình. Phần này trình bày các b ớc c bản trong việc xây dựng các ng dụng ClientServer sử dụng Socket làm ph ng tiện giao tiếp theo cả hai chế độ: Có n i kết và không n i kết. 1.2.1. Mô hình Client-Server sử dụng Socket ở chế độ có n i kết (TCP) Giai đoạn 1: Server tạo Socket, gán s hiệu cổng và lắng nghe yêu cầu n i kết. • • • socket(): Server yêu cầu tạo một socket để có thể sử dụng các dịch vụ c a tầng vận chuyển. bind(): Server yêu cầu gán s hiệu cổng (port) cho socket. listen(): Server lắng nghe các yêu cầu n i kết từ các client trên cổng đã đ ợc gán. Server sẵn sàng phục vụ Client. Giai đoạn 2: Client tạo Socket, yêu cầu thiết lập một n i kết với Server. • • socket(): Client yêu cầu tạo một socket để có thể sử dụng các dịch vụ c a tầng vận chuyển, thông th ng hệ th ng tự động gán một s hiệu cổng còn rảnh cho socket c a Client. connect(): Client g i yêu cầu n i kết đến server có địa chỉ IP và Port xác định. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 61 Khoa Công Nghệ Thông Tin - Đại Học Cần Th • - Giáo Trình Lập Trình Truyền Thông accept(): Server chấp nhận n i kết c a client, khi đó một kênh giao tiếp ảo đ ợc hình thành, Client và server có thể trao đổi thông tin với nhau thông qua kênh ảo này. Giai đoạn 3: Trao đổi thông tin giữa Client và Server. • • • Sau khi chấp nhận yêu cầu n i kết, thông th ng server thực hiện lệnh read() và nghẽn cho đến khi có thông điệp yêu cầu (Request Message) từ client g i đến. Server phân tích và thực thi yêu cầu. Kết quả sẽ đ ợc g i về client bằng lệnh write(). Sau khi g i yêu cầu bằng lệnh write(), client ch nhận thông điệp kết quả (ReplyMessage) từ server bằng lệnh read(). Trong giai đoạn này, việc trao đổi thông tin giữa Client và Server phải tuân th giao th c c a ng dụng (Dạng th c và ý nghĩa c a các thông điệp, qui tắc bắt tay, đồng bộ hóa,... ). Thông th ng Client sẽ là ng i g i yêu cầu đến Server tr ớc. Nếu chúng ta phát triển ng dụng theo các Protocol đã định nghĩa sẵn, chúng ta phải tham khảo và tuân th đúng những qui định c a giao th c. Bạn có thể tìm đọc mô tả chi tiết c a các Protocol đã đ ợc chuẩn hóa trong các tài liệu RFC (Request For Comments). Ng ợc lại, nếu chúng ta phát triển một ng dụng Client-Server riêng c a mình, thì công việc đầu tiên chúng ta phải thực hiện là đi xây dựng Protocol cho ng dụng. Giai đoạn 4: Kết thúc phiên làm việc. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 62 Khoa Công Nghệ Thông Tin - Đại Học Cần Th • - Giáo Trình Lập Trình Truyền Thông Các câu lệnh read(), write() có thể đ ợc th c hiện nhiều lần (ký hiệu bằng hình ellipse). Kênh ảo sẽ bị xóa khi Server hoặc Client đóng socket bằng lệnh close(). • Nh vậy toàn bộ tiến trình diễn ra nh sau: 1.2.2. Mô hình Client-Server sử dụng Socket ở chế độ không n i kết (UDP) Giai đoạn 1: Server tạo Socket - gán s hiệu cổng. o socket(): Server yêu cầu tạo một socket để có thể sử dụng các dịch vụ c a tầng vận chuyển. o bind(): Server yêu cầu gán s hiệu cổng cho socket.. Giai đoạn 2: Client tạo Socket. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 63 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Giai đoạn 3: Trao đổi thông tin giữa Client và Server. Sau khi tạo Socket xong, Client và Server có thể trao đổi thông tin qua lại với nhau thông qua hai hàm sendto() và recvfrom(). Đ n vị dữ liệu trao đổi giữa Client và Server là các Datagram Package (Gói tin th tín). Protocol c a ng dụng phải định nghĩa khuôn dạng và ý nghĩa c a các Datagram Package. Mỗi Datagram Package có ch a thông tin về địa chỉ ng i g i và ng i nhận (IP, Port). 1.3. Socket d ới ngôn ngữ Java Java hỗ trợ lập trình mạng thông qua các lớp trong gói java.net. Một s lớp tiêu biểu đ ợc dùng cho lập trình Client-Server sử dụng socket làm ph ng tiện giao tiếp nh : • • • • • InetAddress: Lớp này quản lý địa chỉ Internet bao gồm địa chỉ IP và tên máy tính. Socket: Hỗ trợ các ph ng th c liên quan đến Socket cho ch ng trình Client chế độ có n i kết. ServerSocket: Hỗ trợ các ph ng th c liên quan đến Socket cho ch ng trình Server chế độ có n i kết. DatagramSocket: Hỗ trợ các ph ng th c liên quan đến Socket chế độ không n i kết cho cả Client và Server. DatagramPacket: Lớp cài đặt gói tin dạng th tín ng i dùng (Datagram Packet) trong giao tiếp giữa Client và Server chế độ không n i kết. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 64 Khoa Công Nghệ Thông Tin - Đại Học Cần Th 1.3.1. Xây dựng ch - Giáo Trình Lập Trình Truyền Thông ng trình Client ở chế độ có n i kết Các b ớc tổng quát: 1. M một socket n i kết đến server đã biết địa chỉ IP (hay tên miền) và s hiệu cổng. 2. Lấy InputStream và OutputStream gán với Socket. 3. Tham khảo Protocol c a dịch vụ để định dạng đúng dữ liệu trao đổi với Server. 4. Trao đổi dữ liệu với Server nh vào các InputStream và OutputStream. 5. Đóng Socket tr ớc khi kết thúc ch ng trình. 1.3.1.1. Lớp java.net.Socket Lớp Socket hỗ trợ các ph ng th c cần thiết để xây dựng các ch ng trình client sử dụng socket chế độ có n i kết. D ới đây là một s ph ng th c th ng dùng để xây dựng Client: public Socket(String HostName, int PortNumber) throws IOException Ph ng th c này dùng để n i kết đến một server có tên là HostName, cổng là PortNumber. Nếu n i kết thành công, một kênh ảo sẽ đ ợc hình thành giữa Client và Server. • • HostName: Địa chỉ IP hoặc tên logic theo dạng tên miền. PortNumber: có giả trị từ 0 ..65535 Ví dụ: M socket và n i kết đến Web Server c a khoa Công Nghệ Thông Tin, Đại Học Cần Th : Socket s = new Socket(“www.cit.ctu.edu.vn”,80); Hoặc: Socket s = new Socket(“203.162.36.149”,80); public InputStream getInputStream() Ph ng th c này trả về InputStream n i với Socket. Ch InputStream này để nhận dữ liệu từ Server g i về. ng trình Client dùng Ví dụ: Lấy InputStream c a Socket s: InputStream is = s.getInputStream(); public OutputStream getOutputStream() Ph ng th c này trả về OutputStream n i với Socket. Ch OutputStream này để g i dữ liệu cho Server. ng trình Client dùng Ví dụ: Lấy OutputStream c a Socket s: OutputStream os = s.getOutputStream(); public close() Ph Server. ng th c này sẽ đóng Socket lại, giải phóng kênh ảo, xóa n i kết giữa Client và Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 65 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Ví dụ: Đóng Socket s: s.close(); 1.3.1.2. Ch ng trình TCPEchoClient Trên hệ th ng UNIX, Dịch vụ Echo đ ợc thiết kế theo kiến trúc Client-Server sử dụng Socket làm ph ng tiện giao tiếp. Cổng mặc định dành cho Echo Server là 7, bao gồm cả hai chế độ có n i kết và không n i kết. Ch ng trình TCPEchoClient sẽ n i kết đến EchoServer chế độ có n i kết, lần l ợt g i đến Echo Server 10 ký tự từ ‘0’ đến '9', ch nhận kết quả trả về và hiển thị chúng ra màn hình. Hãy l u ch ng trình sau vào tập tin TCPEchoClient.java import java.io.*; import java.net.Socket; public class TCPEchoClient{ public static void main(String args[]){ try { Socket s = new Socket(args[0],7); // N i kết đến Server InputStream is = s.getInputStream(); // Lấy InputStream OutputStream os = s.getOutputStream(); // Lấy OutputStream for (int i='0'; i<='9';i++){ // Gui ‘0’ ->’9’ den EchoServer os.write(i); // G i 1 ký tự sang Server int ch = is.read(); // Ch nhận 1 ký tự từ Server System.out.print((char)ch); // In ký tự nhận đ ợc ra màn hình } } //try catch(IOException ie){ System.out.println("Loi: Khong tao duoc socket"); } //catch } //main } Biên dịch và thực thi ch ng trình nh sau: Ch ng trình này nhận một đ i s là địa chỉ IP hay tên miền c a máy tính mà đó Echo Server đang chạy. Trong hệ th ng mạng TCP/IP mỗi máy tính đ ợc gán một địa chỉ IP cục bộ là 127.0.0.1 hay có tên là localhost. Trong ví dụ trên, ch ng trình Client n i kết đến Echo Server trên cùng máy với nó. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 66 Khoa Công Nghệ Thông Tin - Đại Học Cần Th 1.3.2. Xây dựng ch - Giáo Trình Lập Trình Truyền Thông ng trình Server ở chế độ có n i kết 1.3.2.1. Lớp java.net.ServerSocket Lớp ServerSocket hỗ trợ các ph ng th c cần thiết để xây dụng các ch ng trình Server sử dụng socket chế độ có n i kết. D ới đây là một s ph ng th c th ng dùng để xây dựng Server: public ServerSocket(int PortNumber); Ph ng th c này tạo một Socket với s hiệu cổng là PortNumber mà sau đó Server sẽ lắng nghe trên cổng này. Ví dụ: Tạo socket cho Server với s hiệu cổng là 7: ServerSocket ss = new ServerSocket(7); public Socket accept() Ph ng th c này lắng nghe yêu cầu n i kết c a các Client. Đây là một ph ng th c hoạt động chế độ nghẽn. Nó sẽ bị nghẽn cho đến khi có một yêu cầu n i kết c a client g i đến. Khi có yêu cầu n i kết c a Client g i đến, nó sẽ chấp nhận yêu cầu n i kết, trả về một Socket là một đầu c a kênh giao tiếp ảo giữa Server và Client yêu cầu n i kết. Ví dụ: Socket ss ch nhận yêu cầu n i kết: Socket s = ss.accept(); Server sau đó sẽ lấy InputStream và OutputStream c a Socket mới s để giao tiếp với Client. 1.3.2.2. Xây dựng ch ng trình Server phục vụ tuần tự Một Server có thể đ ợc cài đặt để phục vụ các Client theo hai cách: phục vụ tuần tự hoặc phục vụ song song. Trong chế độ phục vụ tuần tự, tại một th i điểm Server chỉ chấp nhận một yêu cầu n i kết. Các yêu cầu n i kết c a các Client khác đều không đ ợc đáp ng (đ a vào hàng đợi). Ng ợc lại trong chế độ phục vụ song song, tại một th i điểm Server chấp nhận nhiều yêu cầu n i kết và phục vụ nhiều Client cùng lúc. Các b ớc tổng quát c a một Server phục vụ tuần tự 1. Tạo socket và gán s hiệu cổng cho server. 2. Lắng nghe yêu cầu n i kết. 3. Với một yêu cầu n i kết đ ợc chấp nhận thực hiện các b ớc sau: o Lấy InputStream và OutputStream gắn với Socket c a kênh ảo vừa đ ợc hình thành. o Lặp lại công việc sau: ƒ Ch nhận các yêu cầu (công việc). ƒ Phân tích và thực hiện yêu cầu. ƒ Tạo thông điệp trả l i. ƒ G i thông điệp trả l i về Client. ƒ Nếu không còn yêu cầu hoặc Client kết thúc, đóng Socket và quay lại b ớc 2. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 67 Khoa Công Nghệ Thông Tin - Đại Học Cần Th 1.3.2.3. Ch - Giáo Trình Lập Trình Truyền Thông ng trình STCPEchoServer STCPEchoServer cài đặt một Echo Server phục vụ tuần tự Server lắng nghe trên cổng mặc định s 7. Hãy l u ch ng trình sau vào tập tin STCPEchoServer.java chế độ có n i kết. import java.net.*; import java.io.*; public class STCPEchoServer { public final static int defaultPort = 7; public static void main(String[] args) { try { ServerSocket ss = new ServerSocket(defaultPort); while (true) { try { Socket s = ss.accept(); OutputStream os = s.getOutputStream(); InputStream is = s.getInputStream(); int ch=0; while(true) { ch = is.read(); if(ch == -1) break; os.write(ch); } s.close(); } catch (IOException e) { System.err.println(" Connection Error: "+e); } } } catch (IOException e) { Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 68 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông System.err.println(" Server Creation Error:"+e); } } } Biên dịch và thực thi ch ng trình theo cách sau: M một cửa s DOS khác và thực thi ch nh sau: ng trình TCPEchoClient ta có kết quả Hai ch ng trình này có thể nằm trên hai máy khác nhau. Trong tr ng hợp đó khi thực hiện ch ng trình TCPEchoClient phải chú ý nhập đúng địa chỉ IP c a máy tính đang chạy ch ng trình STCPEchoServer. Xem địa chỉ IP c a một máy tính Windows bằng lệnh ipconfig. 1.3.2.4. Server phục vụ song song Các b ớc tổng quát c a một Server phục vụ song song Server phục vụ song song gồm 2 phần thực hiện song song nhau: • • Phần 1: Xử lý các yêu cầu n i kết. Phần 2: Xử lý các thông điệp yêu cầu từ khách hàng. Có cấu trúc nh hình sau, trong đó Phần 1 là (Dispatcher Thread), Phần 2 là các (Worker Thread) Phần 1: Lặp lại các công việc sau: • Lắng nghe yêu cầu n i kết c a khách hàng. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy Hình 4.5 Server chế độ song song 69 Khoa Công Nghệ Thông Tin - Đại Học Cần Th • - Giáo Trình Lập Trình Truyền Thông Chấp nhận một yêu cầu n i kết. o Tạo kênh giao tiếp ảo mới với khách hàng. o Tạo Phần 2 để xử lý các thông điệp yêu cầu c a khách hàng. Phần 2: Lặp lại các công việc sau: • • • Ch nhận thông điệp yêu cầu c a khách hàng. Phân tích và xử lý yêu cầu. G i thông điệp trả l i cho khách hàng. Phần 2 sẽ kết thúc khi kênh ảo bị xóa đi. Với mỗi Client, trên Server sẽ có một Phần 2 để xử lý yêu cầu c a khách hàng. Nh vậy tại một th i điểm bất kỳ luôn tồn tại 1 Phần 1 và 0 hoặc nhiều Phần 2. Do Phần 2 thực thi song song với Phần 1 cho nên nó đ ợc thiết kế là một Thread. 1.3.2.5. Ch ng trình PTCPEchoServer PTCPEchoServer cài đặt một Echo Server phục vụ song song chế độ có n i kết. Server lắng nghe trên cổng mặc định là 7. Ch ng trình này gồm 2 lớp: • • Lớp TCPEchoServer, cài đặt các ch c năng c a Phần 1 - xử lý các yêu cầu n i kết c a TCPEchoClient. Lớp RequestProcessing, là một Thread cài đặt các ch c năng c a Phần 2 - Xử lý các thông điệp yêu cầu. Hãy l u ch ng trình sau vào tập tin PTCPEchoServer.java import java.net.*; import java.io.*; public class PTCPEchoServer { public final static int defaultPort = 7; // Cổng mặc định public static void main(String[] args) { try { ServerSocket ss = new ServerSocket(defaultPort); //Tạo socket cho server while (true) { try { Socket s = ss.accept(); // Lắng nghe các yêu cầu n i kết RequestProcessing rp = new RequestProcessing(s); // Tạo phần xử lý rp.start(); // Kh i động phần xử lý cho Client hiện tại } catch (IOException e) { System.out.println("Connection Error: "+e); } } } catch (IOException e) { System.err.println("Create Socket Error: "+e); } } } Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 70 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông class RequestProcessing extends Thread { Socket channel; //Socket c a kênh ảo n i với Client hiện tại public RequestProcessing(Socket s){ channel = s; // Nhận socket c a kênh ảo n i với Client } public void run() { try { OutputStream os = channel.getOutputStream(); InputStream is = channel.getInputStream(); while (true) { int n = is.read(); // Nhận ký tự từ Client if (n == -1) break; // Thoát nếu kênh ảo bị xóa os.write(n); // G i ký tự nhận đ ợc về Client } } catch (IOException e) { System.err.println("Request Processing Error: "+e); } } } Biên dịch và thực thi ch ng trình nh sau: Sau đó m thêm 2 c a sổ DOS khác để thực thi ch ng trình TCPEchoClient n i kết tới PTCPEchoServer. Ta sẽ nhận thấy rằng PTCPEchoServer có khả năng phục vụ đồng th i nhiều Client. 1.3.3. Xây dựng ch ng trình Client - Server ở chế độ không n i kết Khi sử dụng socket, ta có thể chọn giao th c UDP cho lớp vận chuyển. UDP viết tắt c a User Datagram Protocol, cung cấp c chế vận chuyển không bảo đảm và không n i kết trên mạng IP, ng ợc với giao th c vận chuyển tin cậy, có n i kết TCP. Cả giao th c TCP và UDP đều phân dữ liệu ra thành các gói tin. Tuy nhiên TCP có thêm vào những tiêu đề (Header) vào trong gói tin để cho phép truyền lại những gói tin thất lạc và tập hợp các gói tin lại theo th tự đúng đắn. UDP không cung cấp tính năng Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 71 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông này, nếu một gói tin bị thất lạc hoặc bị lỗi, nó sẽ không đ ợc truyền lại, và th tự đến đích c a các gói tin cũng không gi ng nh th tự lúc nó đ ợc g i đi. Tuy nhiên, về t c độ, UDP sẽ truyền nhanh gấp 3 lần TCP. Cho nên chúng th ng đ ợc dùng trong các ng dụng đòi h i th i gian truyền tải ngắn và không cần tính chính xác cao, ví dụ truyền âm thanh, hình ảnh . . . Mô hình client - server sử dụng lớp ServerSocket và Socket trên sử dụng giao th c TCP. Nếu mu n sử dụng mô hình client - server với giao th c UDP, ta sử dụng hai lớp java.net.DatagramSocket và java.net.DatagramPacket. DatagramSocket đ ợc sử dụng để truyền và nhận các DatagramPacket. Dữ liệu đ ợc truyền đi là một mảng những byte, chúng đ ợc gói vào trong lớp DatagramPacket. Chiều dài c a dữ liệu t i đa có thể đ a vào DatagramPacket là khoảng 60.000 byte (phụ thuộc vào dạng đ ng truyền). Ngoài ra DatagramPacket còn ch a địa chỉ IP và cổng c a quá trình g i và nhận dữ liệu. Cổng trong giao th c TCP và UDP có thể trùng nhau. Trên cùng một máy tính, bạn có thể gán cổng 20 cho socket dùng giao th c TCP và cổng 20 cho socket sử dụng giao th c UDP. 1.3.3.1. Lớp DatagramPacket Lớp này dùng để đóng gói dữ liệu g i đi. D ới đây là các ph dụng để thao tác trên dữ liệu truyền / nhận qua DatagramSocket. ng th c th ng sử public DatagramPacket(byte[] b, int n) • • Là ph ng th c kh i tạo, cho phép tạo ra một DatagramPacket ch a n bytes dữ liệu đầu tiên c a mảng b. (n phải nh h n chiều dài c a mảng b) Ph ng th c trả về một đ i t ợng thuộc lớp DatagramePacket Ví dụ: Tạo DatagramPacket để nhận dữ liệu: byte buff[] = new byte[60000]; // N i ch a dữ liệu nhận đ ợc DatagramPacket inPacket = new Datagrampacket(buff, buff.lenth); public DatagramPacket(byte[] b, int n, InternetAddress ia, int port) • • Ph ng th c này cho phép tạo một DatagramPacket ch a dữ liệu và cả địa chỉ c a máy nhận dữ liệu. Ph ng th c trả về một đ i t ợng thuộc lớp DatagramePacket Ví dụ: Tạo DatagramPacket ch a chuỗi "My second UDP Packet", với địa chỉ máy nhận là www.cit.ctu.edu.vn, cổng c a quá trình nhận là 19: try {//Địa chỉ Internet c a máy nhận InetAddress ia = InetAddess.getByName("www.cit.ctu.edu.vn"); int port = 19; // Cổng c a socket nhận String s = "My second UDP Packet"; // Dữ liệu g i đi byte[] b = s.getBytes(); // Đổi chuỗi thành mảng bytes // Tạo gói tin g i đi DatagramPacket outPacket = new DatagramPacket(b, b.length, ia, port); } catch (UnknownHostException e) { Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 72 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông System.err.println(e); } Các ph ng th c lấy thông tin trên một DatagramPacket nhận đ ợc Khi nhận đ ợc một DatagramPacket từ một quá trình khác g i đến, ta có thể lấy thông tin trên DatagramPacket này bằng các ph ng th c sau: • • • • public synchronized() InternetAddress getAddress() : Địa chỉ máy g i public synchronized() int getPort() : Cổng c a quá trình g i public synchronized() byte[] getData() : Dữ liệu từ gói tin public synchronized() int getLength() : Chiều dài c a dữ liệu trong gói tin Các ph ng th c đặt thông tin cho gói tin gởi Tr ớc khi g i một DatagramPacket đi, ta có thể đặt thông tin trên DatagramPacket này bằng các ph ng th c sau: • • • • public synchronized() void setAddress(IntermetAddress dis) : Đặt địa chỉ máy nhận. public synchronized() void setPort(int port) : Đặt cổng quá trình nhận public synchronized() void setData(byte buffer[]) : Đặt dữ liệu g i public synchronized() void setLength(int len) : Đặt chiều dài dữ liệu g i 1.3.3.2. Lớp DatagramSocket Lớp này hỗ trợ các ph ng th c sau để g i / nhận các DatagramPacket public DatagramSocket() throws SocketException • Tạo Socket kiểu không n i kết cho Client. Hệ th ng tự động gán s hiệu cổng ch a sử dụng cho socket. Ví dụ: Tạo một socket không n i kết cho Client: try{ DatagramSocket ds = new DatagramSocket(); } catch(SocketException se) { System.out.print("Create DatagramSocket Error: "+se); } public DatagramSocket(int port) throws SocketException • Tạo Socket kiểu không n i kết cho Server với s hiệu cổng đ ợc xác định trong tham s (port). Ví dụ: Tạo một socket không n i kết cho Server với s hiệu cổng là 7: try{ DatagramSocket dp = new DatagramSocket(7); } catch(SocketException se) { System.out.print("Create DatagramSocket Error: "+se); } Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 73 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông public void send(DatagramPacket dp) throws IOException • Dùng để g i một DatagramPacket đi. Ví dụ: G i chuỗi "My second UDP Packet", cho quá trình www.cit.ctu.edu.vn, cổng nhận là 19: địa chỉ try { DatagramSocket ds = new DatagramSocket(); //Tạo Socket //Địa chỉ Internet c a máy nhận InetAddress ia = InetAddess.getByName("www.cit.ctu.edu.vn"); int port = 19; // Cổng c a quá trình nhận String s = "My second UDP Packet"; // Dữ liệu cần g i byte[] b = s.getBytes(); // Đổi sang mảng bytes // Tạo gói tin DatagramPacket outPacket = new DatagramPacket(b, b.length, ia, port); ds.send(outPacket); // G i gói tin đi } catch (IOException e) { System.err.println(e); } public synchronized IOException • void receive(Datagrampacket dp) throws Ch nhận một DatagramPacket. Quá trình sẽ bị nghẽn cho đến khi có dữ liệu đến. Ví dụ: try { DatagramSocket ds = new DatagramSocket(); //Tạo Socket byte[] b = new byte[60000]; // N i ch a dữ liệu nhận đ ợc DatagramPacket inPacket = new DatagramPacket(b, b.length); // Tạo gói tin ds.receive(inPacket); // Ch nhận gói tin } catch (IOException e) { System.err.println(e); } 1.3.3.3. Ch ng trình UDPEchoServer Ch ng trình UDPEchoServer cài đặt Echo Server chế độ không n i kết, cổng mặc định là 7. Ch ng trình ch nhận từng gói tin, lấy dữ liệu ra kh i gói tin nhận đ ợc và g i ng ợc dữ liệu đó về Client. L u ch ng trình sau vào tập tin UDPEchoServer.java Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 74 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông import java.net.*; import java.io.*; public class UDPEchoServer { public final static int port = 7; // Cổng mặc định c a Server public static void main(String[] args) { try { DatagramSocket ds = new DatagramSocket(port); // Tạo Socket với cổng là 7 byte[] buffer = new byte[6000]; // Vùng đệm ch a dữ liệu cho gói tin nhận while(true) { // Tạo gói tin nhận DatagramPacket incoming = new DatagramPacket(buffer,buffer.length); ds.receive(incoming); // Ch nhận gói tin g i đến // Lấy dữ liệu kh i gói tin nhận String theString = new String(incoming.getData(),0,incoming.getLength()); // Tạo gói tin g i ch a dữ liệu vừa nhận đ ợc DatagramPacket outsending = new DatagramPacket(theString.getBytes(), incoming.getLength(),incoming.getAddress(), incoming.getPort()); ds.send(outsending); } } catch (IOException e) { System.err.println(e); } } } Biên dịch và thực thi ch 1.3.3.4. Ch ng trình nh sau ng trình UDPEchoClient Ch ng trình này cho phép ng i sử dụng nhận các chuỗi từ bàn phím, g i chuỗi sang EchoServer chế độ không n i kết cổng s 7, ch nhận và in dữ liệu từ Server g i về ra màn hình. L u ch ng trình sau vào tập tin UDPEchoClient.java Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 75 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông import java.net.*; import java.io.*; public class UDPEchoClient extends Object{ public final static int serverPort = 7; // Cổng mặc định c a Echo Server public static void main(String[] args) { try { if (args.length ==0) { // Kiểm tra tham s , là địa chỉ c a Server System.out.print("Syntax: java UDPClient HostName"); return; } DatagramSocket ds = new DatagramSocket(); // Tạo DatagramSocket InetAddress server = InetAddress.getByName(args[0]); // Địa chỉ Server while(true) { InputStreamReader isr = new InputStreamReader(System.in); // Nhập BufferedReader br = new BufferedReader(isr); // một chuỗi String theString = br.readLine(); // từ bàn phím byte[] data = theString.getBytes(); // Đổi chuỗi ra mảng bytes // Tạo gói tin g i DatagramPacket dp = new DatagramPacket(data,data.length,server, serverPort); ds.send(dp); // Send gói tin sang Echo Server byte[] buffer = new byte[6000]; // Vùng đệm cho dữ liệu nhận // Gói tin nhận DatagramPacket incoming = new DatagramPacket(buffer, buffer.length); ds.receive(incoming); // Ch nhận dữ liệu từ EchoServer g i về // Đổi dữ liệu nhận đ ợc dạng mảng bytes ra chuỗi và in ra màn hình System.out.println(new String(incoming.getData(), 0, incoming.getLength())); } } catch (IOException e) { System.err.println(e); } } } Biên dịch và thực thi ch ng trình nh sau: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 76 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Chú ý, khi thực hiện ch ng trình UDPEchoClient phải đ a vào đ i s là địa chỉ c a máy tính đang thực thi ch ng trình UDPEchoServer. Trong ví dụ trên, Server và Client cùng chạy trên một máy nên địa chỉ c a UDPEchoServer là localhost (hay 127.0.0.1). Nếu UDPEchoServer chạy trên máy tính khác thì khi thực thi, ta phải biết đ ợc địa chỉ IP c a máy tính đó và cung cấp vào đ i s c a ch ng trình. Chẳng hạn, khi UDPEchoServer đang phục vụ trên máy tính địa chỉ 172.18.250.211, ta sẽ thực thi UDPEchoClient theo cú pháp sau: java UDPEchoClient 172.18.250.211 1.4. Bài tập áp dụng Ch đề 1: Client ở chế độ có n i kết • Mục đích: Viết các ch • ng trình Client n i kết đến các server theo các Protocol chuẩn. Yêu cầu Sinh viên thực hiện các bài tập sau o Bài 1 : Viết ch ng trình nhận đ i s là một URL. N i kết đến Web Server trong URL nhận đ ợc, lấy trang web về và in ra màn hình theo dạng textfile (html). Ch đề 2: Client - Server chế độ có n i kết • • Mục đích: o Viết các ch Yêu cầu ng trình Client -Server theo chế độ có n i kết. Sinh viên thực hiện các bài tập sau, với mỗi bài tập hãy thiêt kế một Server phục vụ chế độ tuần tự và một Server phục vụ chế độ song song. o Bài 1: Viết ch ng trình theo mô hình Client-Server sử dụng dụng Socket chế độ có n i kết. Trong đó : + Server làm nhiệm vụ đọc một ký tự s từ '0' đến '9'. ( Ví dụ : nhận s 0 : trả về "khong" , 1 : trả về "một" ; ... ... 9 : trả về "chín", nếu nhận ký tự khác s thì trả về "Không phải s nguyên" ). + Client sẽ nhập vào 1 ký tự, gửi qua Server, nhận kết quả trả về từ Server và thể hiện lên màn hình o Bài 2: Viết ch ng trình theo mô hình Client-Server sử dụng Socket chế độ có n i kết. Trong đó : + Server sẽ nhận các yêu cầu là một chuỗi có khuôn dạng nh sau: "OP Operant1 Operant2\n" Trong đó: - OP là một ký tự chỉ phép toán mu n thực hiện: '+','-', '*', '/'. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 77 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông - Operant1, Operant2 là đ i s c a phép toán. - Các thành phần trên cách nhau b i 1 ký tự trắng ' '. - Kết thúc yêu cầu bằng ký tự xu ng dòng '\n'. Mỗi khi server nhận đ ợc một thông điệp nó sẽ thực hiện phép toán: Operant1 OP Operant2 để cho ra kết quả, sau đó đổi kết quá thành chuỗi và g i về Client. + Client cho phép ng i dùng nhập các phép toán mu n tính theo cách th c thông th ng. Ví dụ: 100+200. Client tạo ra thông điệp yêu cầu theo đúng dạng do Server qui định, mô tả về phép toán mu n Server thực thi, rồi g i sang Server, ch nhận kết quả trả về và in ra màn hình. Ch đề 3: Client-Server ở chế độ không n i kết • • Mục đích: o Viết các ch ng trình Client -Server theo chế độ không n i kết. Yêu cầu o Bài 1 : Viết ch ng trình Talk theo chế độ không n i kết. Cho phép hai ng i ngồi trên hai máy tính có thể tán gẫu (chat) với nhau. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 78 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông CH NG 5 RPC và RMI Mục đích Ch ng này nhằm giới thiệu cách th c xây dựng các ng dụng phân tán bằng các c chế gọi th tục từ xa (RPC - Remote Procedure Call và RMI - Remote Method Invocation) Yêu cầu Sau khi hoàn tất ch • • • • • • • • • • ng này, bạn có thể: Định nghĩa đ ợc ng dụng phân tán là gì. Trình bày đ ợc kiến trúc c a một ng dụng phân tán xây dựng theo c chế gọi th tục từ xa (RPC). Trình bày đ ợc kiến trúc c a một ng dụng phân tán (hay còn gọi ng dụng đ i t ợng phân tán ) xây dựng theo c chế RMI c a Java. Trình bày đ ợc các c chế liên quan khi xây dựng một ng dụng theo kiểu RMI. Trình bày đ ợc c chế vận hành c a một ng dụng theo kiểu RMI. Giải thích đ ợc vai trò rmiregistry server. Liệt kê đ ợc các lớp c a java hỗ trợ xây dựng các ng dụng kiểu RMI. Trình bày chi tiết các b ớc phải qua khi xây dựng một ng dụng theo kiểu RMI. Biên soạn, biên dịch và thực thi thành công ch ng trình minh họa Hello. Phân tích, thiết kế và cài đặt đ ợc các ch ng trình theo c chế RMI để giải quyết các vấn đề cụ thể. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 79 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.1. Lời gọi th tục xa (RPC- Remote Procedure Call) 1.1.1. Giới thiệu L i gọi th tục xa là một c chế cho phép một ch ng trình có thể gọi thực thi một th tục (hay hàm) trên một máy tính khác. Trong ch ng trình lúc này, tồn tại hai loại th tục: th tục cục bộ và th tục xa. • • Th tục cục bộ là th tục đ ợc định nghĩa, cài đặt và thực thi tại máy c a ch ng trình. Th tục xa là th tục đ ợc định nghĩa, cài đặt và thực thi trên một máy tính khác. Cú pháp giữa l i gọi th tục cục bộ và xa thì gi ng nhau. Tuy nhiên, khi một th tục xa đ ợc gọi đến, một thành phần c a ch ng trình gọi là Stub sẽ chuyển h ớng để kích hoạt một th tục t ng ng nằm trên một máy tính khác với máy c a ch ng trình gọi. Đ i với ng i lập trình, việc gọi th tục xa và th tục cục bộ thì gi ng nhau về mặt cú pháp. Đây chính là c chế cho phép đ n giản hóa việc xây dựng các ng dụng ClientServer. Trong hệ th ng RPC, Server chính là máy tính cung cấp các th tục xa cho phép các ch ng trình trên các máy tính khác gọi thực hiện. Client chính là các ch ng trình có thể gọi các th tục xa trong quá trình tính toán c a mình. Một Client có thể gọi th tục xa c a nhiều h n một máy tính. Nh vậy sự thực thi c a ch ng trình Client lúc này không còn gói gọn trên một máy tính c a Client mà nó trải rộng trên nhiều máy tính khác nhau. Đây chính là mô hình c a ng dụng phân tán (Distributed Application). 1.1.2. Kiến trúc c a ch th tục xa ng trình Client-Server cài đặt theo c chế lời gọi Một ng dụng Client-Server theo c chế RPC đ ợc xây dựng gồm có sáu phần nh s đồ d ới đây: Hình 5.1 Kiến trúc ch Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy ng trình kiểu RPC 80 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Phần Client là một quá trình ng i dùng, n i kh i tạo một l i gọi th tục từ xa. Mỗi l i gọi th tục xa trên phần Client sẽ kích hoạt một th tục cục bộ t ng ng nằm trong phần Stub c a Client. Phần ClientStub cung cấp một bộ các hàm cục bộ mà phần Client có thể gọi. Mỗi một hàm c a ClientStub đại diện cho một hàm xa đ ợc cài đặt và thực thi trên Server. Mỗi khi một hàm nào đó c a ClientStub đ ợc gọi b i Client, ClientStub sẽ đóng gói một thông điệp để mô tả về th tục xa t ng ng mà Client mu n thực thi cùng với các tham s nếu có. Sau đó nó sẽ nh hệ th ng RPCRuntime cục bộ g i thông điệp này đến phần Server Stub c a Server. Phần RPCRuntime quản lý việc truyền thông điệp thông qua mạng giữa máy Client và máy Server. Nó đảm nhận việc truyền lại, báo nhận, chọn đ ng gói tin và mã hóa thông tin. RPCRuntime trên máy Client nhận thông điệp yêu cầu từ ClientStub, g i nó cho RPCRuntime trên máy Server bằng lệnh send(). Sau đó gọi lệnh wait() để ch kết quả trả về từ Server. Khi nhận đ ợc thông tiệp từ RPCRuntime c a Client g i sang, RPCRuntime bên phía server chuyển thông điệp lên phần ServerStub. ServerStub m thông điệp ra xem, xác định hàm cùng với các tham s c a nó. ServerStub gọi một th tục t xa mà Client mu n thực hiện ng ng nằm trên phần Server. Khi nhận đ ợc yêu cầu c a ServerStub, Server cho thực thi th tục đ ợc yêu cầu và g i kết quả thực thi đ ợc cho ServerStub. ServerStub đóng gói kết quả thực trong một gói tin trả l i, chuyển cho phần RPCRuntime cục bộ để nó g i sang RPCRuntime c a Client . RPCRuntime bên phía Client chuyển gói tin trả l i nhận đ ợc cho phần ClientStub. ClientStub m thông điệp ch a kết quả thực thi về cho Client tại vị trí phát ra l i gọi th tục xa. Trong các thành phần trên, RPCRuntime đ ợc cung cấp b i hệ th ng. ClientStub và ServerStub có thể tạo ra th công (phải lập trình) hay có thể tạo ra bằng các công cụ cung cấp b i hệ th ng. C chế RPC đ ợc hỗ trợ b i hầu hết các hệ điều hành mạng cũng nh các ngôn ngữ lập trình. 1.2. Kích hoạt ph ng th c xa (RMI- Remote Method Invocation ) 1.2.1. Giới thiệu RMI là một sự cài đặt c chế RPC trong ngôn ngữ lập trình h ớng đ i t ợng Java. Hệ th ng RMI cho phép một đ i t ợng chạy trên một máy ảo Java này có thể kích hoạt một ph ng th c c a một đ i t ợng đang chạy trên một máy ảo Java khác. Đ i t ợng có ph ng th c đ ợc gọi từ xa gọi là các đ i t ợng xa (Remote Object). Một ng dụng RMI th một ch ng trình Client. ng bao gồm 2 phần phân biệt: Môt ch Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy ng trình Server và 81 Khoa Công Nghệ Thông Tin - Đại Học Cần Th • • - Giáo Trình Lập Trình Truyền Thông Ch ng trình Server tạo một s các Remote Object, tạo các tham chiếu (reference) đến chúng và ch những ch ng trình Client kích hoạt các ph ng th c c a các Remote Object này. Ch ng trình Client lấy một tham chiếu đến một hoặc nhiều Remote Object trên Server và kích hoạt các ph ng th c từ xa thông qua các tham chiếu. Một ch ng trình Client có thể kích hoạt các ph ng th c xa trên một hay nhiều Server. T c là sự thực thi c a ch ng trình đ ợc trải rộng trên nhiều máy tính. Đây chính là đặc điểm c a các ng dụng phân tán. Nói cách khác, RMI là c chế để xây dựng các ng dụng phân tán d ới ngôn ngữ Java. 1.2.2. Kiến trúc c a ch Kiến trúc một ch d ới đây: ng trình Client-Server theo c chế RMI ng trình Client-Server theo c chế RMI đ ợc mô tả nh hình Hình 5.2 - Kiến trúc ch ng trình kiểu RMI Trong đó: • • • • • Server là ch ng trình cung cấp các đ i t ợng có thể đ ợc gọi từ xa. Client là ch ng trình có tham chiếu đến các ph ng th c c a các đ i t ợng xa trên Server. Stub ch a các tham chiếu đến các ph ng th c xa trên Server. Skeleton đón nhận các tham chiếu từ Stub để kích hoạt ph ng th c t ng ng trên Server. Remote Reference Layer là hệ th ng truyền thông c a RMI. Con đ ng kích hoạt một ph ng th c Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy xa đ ợc mô tả nh hình d ới đây: 82 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông Hình 5.3 C chế hoạt động c a RMI 1.2.3. Các c chế liên quan trong một ng dụng đ i t ợng phân tán Trong một ng dụng phân tán cần có các c chế sau: • • • Cơ chế định vị đối tượng ở xa (Locate remote objects): C chế này xác định cách th c mà ch ng trình Client có thể lấy đ ợc tham chiếu (Stub) đến các đ i t ợng xa. Thông th ng ng i ta sử dụng một Dịch vụ danh bạ (Naming Service) l u giữ các tham khảo đến các đ i t ợng cho phép gọi từ xa mà Client sau đó có thể tìm kiếm. Cơ chế giao tiếp với các đối tượng ở xa (Communicate with remote objects): Chi tiết c a c chế giao tiếp với các đ i t ợng xa đ ợc cài đặt b i hệ th ng RMI. Tải các lớp dạng bytecodes cho các lớp mà nó được chuyển tải qua lại giữa Máy ảo (Load class bytecodes for objects that are passed around): Vì RMI cho phép các ch ng trình gọi ph ng th c từ xa trao đổi các đ i t ợng với các ph ng th c xa d ới dạng các tham s hay giá trị trả về c a ph ng th c, nên RMI cần có c chế cần thiết để tải mã Bytecodes c a các đ i t ợng từ máy ảo này sang máy ảo khác. Hình d ới đây mô tả một ng dụng phân tán d ới RMI sử dụng dịch vụ danh bạ để lấy các tham khảo c a các đ i t ợng xa. Trong đó: • • Server đăng ký tên cho đ i t ợng có thể đ ợc gọi từ xa c a mình với Dịch vụ danh bạ (Registry Server). Client tìm đ i t ợng xa thông qua tên đã đ ợc đăng ký trên Registry Server (looks up) và tiếp đó gọi các ph ng th c xa. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy Hình 5.4 Vai trò c a dịch vụ tên 83 Khoa Công Nghệ Thông Tin - Đại Học Cần Th • - Giáo Trình Lập Trình Truyền Thông Hình minh họa cũng cho thấy cách th c mà hệ th ng RMI sử dụng một WebServer sẵn có để truyền tải mã bytecodes c a các lớp qua lại giữa Client và Server. 1.2.4. C chế vận hành c a c a một RMI ng dụng Client-Server theo kiểu Tiến trình vận hành c a một ng dụng Client-Server theo kiểu RMI diễn ra nh sau: ƒ B ớc 1: Server tạo ra các đ i t ợng cho phép gọi từ xa cùng với các Stub và Skeleton c a chúng. ƒ B ớc 2: Server sử dụng lớp Naming để đăng ký tên cho một đ i t ợng từ xa (1). ƒ B ớc 3: Naming đăng ký Stub c a đ i t ợng từ xa với Registry Server (2). ƒ B ớc 4: Registry Server sẵn sàng cung cấp tham thảo đến đ i t ợng từ xa khi có yêu cầu (3). ƒ Client yêu cầu Naming định vị đ i t ợng xa qua tên đã đ ợc đăng ký (ph ng th c lookup) với dịch vụ tên (4). ƒ Naming tải Stub c a đ i t ợng xa từ dịch vụ tên mà đ i t ợng xa đã đăng ký về Client (5). ƒ Cài đặt đ i t ợng Stub và trả về tham khảo đ i t ợng xa cho Client (6). ƒ Client thực thi một l i gọi ph Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy ng th c xa thông qua đ i t ợng Stub (7). 84 Khoa Công Nghệ Thông Tin - Đại Học Cần Th 1.2.5. Các lớp hỗ trợ ch - Giáo Trình Lập Trình Truyền Thông ng trình theo kiểu Client-Server trong Java Java hỗ trợ các lớp cần thiết để cài đặt các ng dụng Client-Server theo kiểu RMI trong các gói: java.rmi. Trong s đó các lớp th ng đ ợc dùng là: • • • • • • java.rmi.Naming java.rmi.RMISecurityManager java.rmi.RemoteException; java.rmi.server.RemoteObject java.rmi.server.RemoteServer java.rmi. server.UnicastRemoteObject 1.3. Xây dựng một ng dụng phân tán với RMI Xây dụng một ng dụng phân tán bằng c chế RMI gồm các b ớc sau: 1. 2. 3. 4. Thiết kế và cài đặt các thành phần c a ng dụng. Biên dịch các ch ng trình nguồn và tạo ra Stub và Skeleton. Tạo các lớp có thể truy xuất từ mạng cần thiết. Kh i tạo ng dụng 1.3.1. Thiết kế và cài đặt các thành phần c a ng dụng. Đầu tiên bạn phải xác định lớp nào là lớp cục bộ, lớp nào là lớp đ ợc gọi từ xa. Nó bao gồm các b ớc sau: • • • Định nghĩa các giao diện cho các phương thức ở xa (remote interfaces): Một remote interface mô tả các ph ng th c mà nó có thể đ ợc kích hoạt từ xa b i các Client. Đi cùng với việc định nghĩa Remote Interface là việc xác định các lớp cục bộ làm tham s hay giá trị trả về c a các ph ng th c đ ợc gọi từ xa. Cài đặt các đối tượng từ xa (remote objects): Các Remote Object phải cài đặt cho một hoặc nhiều Remote Interfaces đã đ ợc định nghĩa. Các lớp c a Remote Object class cài đặt cho các ph ng th c đ ợc gọi từ xa đã đ ợc khai báo trong Remote Interface và có thể định nghĩa và cài đặt cho cả các ph ng th c đ ợc sử dụng cục bộ. Nếu có các lớp làm đ i s hay giá trị trả về cho các ph ng th c đ ợc gọi từ xa thì ta cũng định nghĩa và cài đặt chúng. Cài đặt các chương trình Client: Các ch ng trình Client có sử dụng các Remote Object có thể đ ợc cài đặt bất kỳ th i điểm nào sau khi các Remote Interface đã đ ợc định nghĩa. 1.3.2. Biên dịch các tập tin nguồn và tạo Stubs và Skeleton Giai đoạn này gồm 2 b ớc: B ớc th nhất là dùng ch ng trình biên dịch javac để biên dịch các tập tin nguồn nh các remote interface, các lớp cài đặt cho các remote interface, lớp server, lớp client và các lớp liên quan khác. Kế tiếp ta dùng trình biện dịch rmic để tạo ra stub và skeleton cho các đ i t ợng từ xa từ các lớp cài đặt cho các remote interface. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 85 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.3.3. Tạo các lớp có thể truy xuất từ mạng Tạo một tập tin ch a tất cả các file có liên quan nh các remote interface stub, các lớp hỗ trợ mà chúng cần thiết phải tải về Client và làm cho tập tin này có thể truy cập đến thông qua một Web server. 1.3.4. Thực thi ng dụng Thực thi ng dụng bao gồm việc thực thi rmiregistry server, thực thi server, và thực thi client. Tóm lại các công việc phải làm là: • • • • • • • • Tạo giao diện (interface) khai báo các ph ng th c đ ợc gọi từ xa c a đ i t ợng. Tạo lớp cài đặt (implement) cho giao diện đã đ ợc khai báo. Viết ch ng trình Server. Viết ch ng trình Client. Dịch các tập tin nguồn theo dạng RMI để tạo ra các lớp t ng ng và stub cho client, skeleton cho server. Kh i động dịch vụ registry. Thực hiện ch ng trình Server. Thực thi ch ng trình Client. 1.3.4. Ví dụ minh họa Trong ví dụ này chúng ta định nghĩa một ph ng th c String sayHello() đ ợc gọi từ xa. Mỗi khi ph ng th c này đ ợc kích hoạt nó sẽ trả về chuỗi "Hello World" cho Client gọi nó. D ới đây là các b ớc để xây dựng ng dụng: B ớc 01: Tạo giao diện (interface) khai báo các ph xa c a đ i t ợng. o ng th c đ ợc gọi từ Cú pháp tổng quát: import java.rmi.Remote; import java.rmi.RemoteException; public interface InterfaceName extends Remote { ReturnType remoteMethodOne() throws RemoteException; ReturnType remoteMethodTwo() throws RemoteException; ... } o Định nghĩa remote interface có tên là HelloItf, có ph gọi từ xa là String sayHello() nh sau: ng th c đ ợc import java.rmi.Remote; import java.rmi.RemoteException; public interface HelloItf extends Remote { String sayHello() throws RemoteException; } Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 86 Khoa Công Nghệ Thông Tin - Đại Học Cần Th L u ch - Giáo Trình Lập Trình Truyền Thông ng trình này vào tập tin HelloItf.java B ớc 02: Tạo lớp cài đặt (implement) cho giao diện đã đ ợc khai báo: o Cú pháp tổng quát: import java.rmi. server.UnicastRemoteObject; import java.rmi.RemoteException; public class RemoteClass extends UnicastRemoteObject implements InterfaceName { public RemoteClass() throws RemoteException { super(); ....... // Implement of Method } public ReturnType remoteMethodOne() throws RemoteException { ....... // Implement of Method } public ReturnType remoteMethodTwo() throws RemoteException { ....... // Definition of Method } } o Định nghĩa lớp cài đặt có tên là Hello cài đặt cho remote interface HelloItf import java.rmi. server.UnicastRemoteObject; import java.rmi.RemoteException; public class Hello extends UnicastRemoteObject implements HelloItf { public Hello() throws RemoteException { super(); } public String sayHello() { return "Hello World !"; } } L u ch ng trình này vào tập tin Hello.java B ớc 03: Viết ch o ng trình Server: Cú pháp tổng quát: import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.RMISecurityManager; public class ServerName { public static void main(String args[]) { if (System.getSecurityManager() == null) { // Cài đặt c chế bảo mật System.setSecurityManager(new RMISecurityManager()); } try { // Tạo các đ i t ợng từ xa Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 87 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông RemoteClass remoteObject = new RemoteClass(); // Đăng ký tên cho các đ i t ợng từ xa Naming.rebind(“RegistryName", remoteObject); ... } catch (Exception e) { System.out.println(”Error: . . .” + e); } } } o Tạo server có tên HelloServer ch a một đ i t ợng từ xa obj thuộc lớp cài đặt Hello. Đăng ký tên cho đ i t ợng obj là HelloObject import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.RMISecurityManager; public class HelloServer { public static void main(String args[]) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { Hello obj = new Hello(); Naming.rebind("HelloObject", obj); System.out.println("HelloObject is registried"); } catch (Exception e) { System.out.println("Error: " + e); } } } L u ch ng trình này vào tập tin HelloServer.java B ớc 04: Viết ch o ng trình Client: Cú pháp tổng quát: import java.rmi.Naming; import java.rmi.RemoteException; public class Client { public static void main(String args[]) { String remoteObjectURL = "rmi://NameServer/RegistryName”; Interfacename object = null; try { object = (InterfaceName)Naming.lookup(remoteObjectURL); object.remoteMethodOne(); ... } catch (Exception e) { Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 88 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông System.out.println(" Error: ”+ e); } } } o Tạo client có tên là HelloClient, tìm đ i t ợng HelloObject trên rmiregistry chẳng hạn tại địa chỉ 172.18.211.160. Gọi ph ng th c sayHello() và in kết quả trả về ra màn hình. import java.rmi.Naming; import java.rmi.RemoteException; public class HelloClient { public static void main(String args[]) { String helloURL = "rmi://172.18.211.160/HelloObject"; HelloItf object = null; try { object = (HelloItf)Naming.lookup( helloURL); String message = object.sayHello(); System.out.println(message); } catch (Exception e) { System.out.println("Client Error :" + e); } } } L u ch ng trình vào tập tin HelloClient.java B ớc 05: Dịch các tập tin nguồn theo dạng RMI để tạo ra các lớp t ng và stub cho client, skeleton cho server: o ng Cú pháp tổng quát: javac InterfaceName.java RemoteClass.java Server.java Client.java ( Tạo ra các lớp InterfaceName.class RemoteClass.class Server.class Client.class) rmic RemoteClass ( Tạo ra các lớp cho Skeleton và Stub: RemoteClass_Skel.class RemoteClass_Stub.class) o Biên dịch các lớp trong Hello: javac Hello.java HelloItf.java HelloServer.java HelloClient.java rmic Hello.class Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 89 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông B ớc 06: Khởi động dịch vụ rmiregistry o Cú pháp tổng quát: start rmiregistry [port] Cổng mặc định là 1099. o Khới động dịch vụ rmiregistry trên cổng mặc định nh sau: Khi đó rmiregistry server sẽ chạy trên một cửa sổ mới, giữ nguyên cửa sổ này, không đóng nó lại. Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 90 Khoa Công Nghệ Thông Tin - Đại Học Cần Th B ớc 07: Thực hiện ch o - Giáo Trình Lập Trình Truyền Thông ng trình Server Cú pháp tổng quát: java -Djava.security.policy =UrlOfPolicyFile ServerName Trong đó UrlOfPolicyFile là địa chỉ theo dạng URL c a tập tin mô tả chính sách về bảo mật mã nguồn c a Server (policy file). Nó qui định "ai" (ch ng trình, máy tính, quá trình trên) sẽ có quyền download các tập tin c a nó trong đó có stub. Để đ n giản trong phần này ta cho phép tất cả mọi ng i đều có quyền download các tập tin c a Server. Khi triển khai các ng dụng thật sự ta phải có các chính sách bảo mật nghiêm ngặt h n (Tham khảo tài liệu về Security c a Java). File policy có dạng nh sau: grant { // Allow everything for now permission java.security.AllPermission; }; L u nội dung trên vào tập tin có tên policy.java o Thực thi HelloServer với địa tập tin plolicy nằm D:\progs\policy.java B ớc 08: Thực thi ch th mục ng trình Client: Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 91 Khoa Công Nghệ Thông Tin - Đại Học Cần Th o - Giáo Trình Lập Trình Truyền Thông Cú pháp tổng quát java ClientName o Thực thi HelloClient với địa chỉ c a rmiregistry đ a vào trong tham s Để thực thi đ ợc ch ng trình HelloClient cần có hai class nằm cùng th mục với nó là HelloItf.class và Hello_Stub.class. 1.4. Bài tập áp dụng • Mục đích: Xây dựng ng dụng phân tán theo c chế RMI. • Yêu cầu Sinh viên thực hiện các bài tập sau: o Bài 1 : Xây dựng một ng dụng phục vụ việc bán vé máy bay cho các đại lý phân tán các tỉnh thành khác nhau. ng dụng này có các lớp sau: ƒ Lớp chuyến bay: Đại diện cho một chuyến bay ƒ Có các thuộc tính: S hiệu chuyến bay, Ngày gi bay, N i đi, N i đến, Th i gian bay, Tổng s ghế, S l ợng ghế đã bán, S l ợng ghế còn tr ng. ƒ Các ph ng th c trên một chuyến bay: ph ng th c xem thông tin về chuyến bay, ph ng th c mua vé, ph ng th c trả vé. Để phục vụ cho nhiều đại lý các ph ng th c trên thuộc loại đuợc gọi từ xa. ƒ Lớp Server, tạo ra nhiều chuyến bay và duy trì nó để cho phép các đại lý thực hiện các giao dịch trên chuyến bay cụ thể. ƒ Client là ch ng trình cho phép mỗi đại lý đ ợc quyền xem thông tin về chuyến bay, mua vé, trả vé theo yêu cầu. Mục lục Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 92 Khoa Công Nghệ Thông Tin - Đại Học Cần Th CH - Giáo Trình Lập Trình Truyền Thông NG 1..........................................................................................................................1 Tổng quan về lập trình truyền thông ....................................................................................1 1.1. C chế giao tiếp liên quá trình là gì ?.....................................................................2 1.2. Phân loại c chế giao tiếp liên quá trình ................................................................2 1.3. Mô hình tham khảo OSI .........................................................................................3 1.4. Mạng TCP/IP..........................................................................................................6 1.5. Dịch vụ mạng .........................................................................................................7 1.6. Mô hình Client – Server .........................................................................................7 1.6.1. Giới thiệu.........................................................................................................7 1.6.2. Ví dụ về dịch vụ Web......................................................................................8 1.6.3. Các chế độ giao tiếp ........................................................................................9 1.6.3.1. Chế độ nghẽn :..........................................................................................9 1.6.3.2. Chế độ không nghẽn:................................................................................9 1.7. Các kiểu kiến trúc ch ng trình .............................................................................9 1.7.1. Kiến trúc đ n tầng (Single-tier Architecture) ...............................................10 1.7.2. Kiến trúc hai tầng (Two - Tier Architecture) ................................................10 1.7.2.1. Loại Fat Client........................................................................................11 1.7.2.2. Loại Fat Server .......................................................................................12 1.7.3. Kiến trúc đa tầng (N-Tier Architecture)........................................................12 1.8. Bài tập...................................................................................................................13 1.8.1. Bài tập bắt buộc.............................................................................................13 1.8.2. Bài tập gợi ý ..................................................................................................13 Tìm đọc và viết một báo cáo không quá 10 trang về giao th c POP3...............................13 CH NG 2........................................................................................................................14 S l ợc về ngôn ngữ Java ..................................................................................................14 1.1. Giới thiệu về ngôn ngữ Java.................................................................................15 1.1.1. Lịch sử phát triển...........................................................................................15 1.1.2. Khả năng c a ngôn ngữ Java.........................................................................15 1.1.2. Những đặc điểm c a ngôn ngữ Java .............................................................15 1.1.3. Máy ảo Java (JMV - Java Virtual Machine) .................................................15 1.1.4. Hai kiểu ng dụng d ới ngôn ngữ java.........................................................16 1.1.5. Bộ phát triển ng dụng Java (JDK- Java Development Kit) ........................16 1.1.6. Kiểu dữ liệu c bản d ới Java.......................................................................16 1.1.7. Các phép toán c bản ....................................................................................17 Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 93 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.1.8. Qui cách đặt tên trong Java ...........................................................................17 1.2. Ch ng trình ng dụng kiểu Application ............................................................18 1.2.1. Ch ng trình HelloWorld .............................................................................19 1.2.3. Biên soạn ch ng trình bằng phần mềm Notepad c a Ms Windows ...........19 1.2.4. Cài đặt bộ phát triển ng dụng JDK..............................................................20 1.2.5. Biên dịch và thực thi ch ng trình................................................................20 1.2.6. Một s ví dụ...................................................................................................21 1.2.6.1. Hiển thị thông tin ra màn hành...............................................................21 1.2.6.2. Đọc ký tự từ bàn phím............................................................................21 1.3. Các cấu trúc điều khiển trong Java.......................................................................23 1.3.1. Lệnh if – else .................................................................................................23 1.3.2. Phép toán ? ....................................................................................................24 1.3.3. Lệnh switch ...................................................................................................25 1.3.4. Lệnh while.....................................................................................................26 1.3.5. Lệnh do - while..............................................................................................27 1.3.6. Lệnh for .........................................................................................................27 1.3.7. Lệnh break.....................................................................................................28 1.3.8. Lệnh continue ................................................................................................29 1.3.9. Một s vấn đề khác........................................................................................30 1.3.9.1. Đọc đ i s c a ch ng trình ..................................................................30 1.3.9.2. Đổi chuỗi thành s ..................................................................................31 1.4. Ngoại lệ (EXCEPTION) ......................................................................................31 1.5. Một s vấn đề liên quan đến lớp trong Java.........................................................33 1.5.1. Định nghĩa lớp mới........................................................................................33 1.5.2. Phạm vi nhìn thấy c a một lớp......................................................................34 1.5.3. Tính thừa kế...................................................................................................35 1.6. Vào / Ra với Stream ............................................................................................36 1.6.1. Lớp java.io.InputStream................................................................................37 1.6.2. Lớp java.io.OutputStream .............................................................................39 1.6.3. Nhập chuỗi từ một InputStream ....................................................................40 1.6.4. Xuất chuỗi ra một OutputStream ..................................................................41 1.7. Luồng (Thread).....................................................................................................42 1.7.1. Các m c cài đặt luồng ...................................................................................43 1.7.1.1. Tiếp cận luồng Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy m c ng i dùng: ........................................................44 94 Khoa Công Nghệ Thông Tin - Đại Học Cần Th 1.7.1.2. Tiếp cận luồng - Giáo Trình Lập Trình Truyền Thông m c hạt nhân hệ điều hành.........................................44 1.7.2. Luồng trong java ...........................................................................................44 1.7.2.1 Độ u tiên c a luồng ...............................................................................47 1.7.3. Đồng bộ hóa giữa các luồng..........................................................................49 1.8. Bài tập áp dụng.....................................................................................................49 Ch đề 1: C bản về Java ........................................................................................49 Ch đề 2: Thiết kế lớp trong Java ...........................................................................49 Ch đề 3: Thread .....................................................................................................50 CH NG 3........................................................................................................................51 ng dẫn (Pipe) ...................................................................................................................51 1.1. Giới thiệu về ng dẫn ...........................................................................................52 1.2. ng dẫn trong Java...............................................................................................52 1.2.1. Giới thiệu.......................................................................................................52 1.2.2. Các cách tạo ng dẫn.....................................................................................53 1.3. Dịch vụ phản hồi thông tin (Echo Service) ..........................................................53 1.4. Giả lập dịch vụ phản hồi thông tin bằng Pipe ......................................................54 1.4.1. Lớp PipedEchoServer....................................................................................54 1.4.2. Lớp PipedEchoClient ....................................................................................55 1.4.3. Lớp PipedEcho ..............................................................................................55 1.4.5. Biên dịch và thực thi ch CH ng trình................................................................56 NG 4........................................................................................................................57 Socket .................................................................................................................................57 1.1. Giới thiệu về socket..............................................................................................58 1.1.1. Giới thiệu.......................................................................................................58 1.1.2. S hiệu cổng (Port Number) c a socket........................................................58 1.1.3. Các chế độ giao tiếp ......................................................................................60 1.2. Xây dựng ng dụng Client-Server với Socket .....................................................61 1.2.1. Mô hình Client-Server sử dụng Socket chế độ có n i kết (TCP) ..............61 1.2.2. Mô hình Client-Server sử dụng Socket chế độ không n i kết (UDP)........63 1.3. Socket d ới ngôn ngữ Java ..................................................................................64 1.3.1. Xây dựng ch ng trình Client chế độ có n i kết .......................................65 1.3.1.1. Lớp java.net.Socket................................................................................65 1.3.1.2. Ch ng trình TCPEchoClient ................................................................66 1.3.2. Xây dựng ch ng trình Server Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy chế độ có n i kết ......................................67 95 Khoa Công Nghệ Thông Tin - Đại Học Cần Th - Giáo Trình Lập Trình Truyền Thông 1.3.2.1. Lớp java.net.ServerSocket .....................................................................67 1.3.2.2. Xây dựng ch 1.3.2.3. Ch ng trình Server phục vụ tuần tự .....................................67 ng trình STCPEchoServer .............................................................68 1.3.2.4. Server phục vụ song song.......................................................................69 1.3.2.5. Ch ng trình PTCPEchoServer .............................................................70 1.3.3. Xây dựng ch ng trình Client - Server chế độ không n i kết ...................71 1.3.3.1. Lớp DatagramPacket ..............................................................................72 1.3.3.2. Lớp DatagramSocket..............................................................................73 1.3.3.3. Ch ng trình UDPEchoServer...............................................................74 1.3.3.4. Ch ng trình UDPEchoClient ...............................................................75 1.4. Bài tập áp dụng.....................................................................................................77 CH NG 5........................................................................................................................79 RPC và RMI .......................................................................................................................79 1.1. L i gọi th tục xa (RPC- Remote Procedure Call) ..............................................80 1.1.1. Giới thiệu.......................................................................................................80 1.1.2. Kiến trúc c a ch tục xa 80 ng trình Client-Server cài đặt theo c chế l i gọi th Hình 5.1 Kiến trúc ch ng trình kiểu RPC........................................................................80 1.2. Kích hoạt ph ng th c xa (RMI- Remote Method Invocation ) .........................81 1.2.1. Giới thiệu.......................................................................................................81 1.2.2. Kiến trúc c a ch ng trình Client-Server theo c chế RMI .........................82 1.2.3. Các c chế liên quan trong một ng dụng đ i t ợng phân tán .....................83 1.2.4. C chế vận hành c a c a một ng dụng Client-Server theo kiểu RMI ........84 1.2.5. Các lớp hỗ trợ ch ng trình theo kiểu Client-Server trong Java ..................85 1.3. Xây dựng một ng dụng phân tán với RMI .........................................................85 1.3.1. Thiết kế và cài đặt các thành phần c a ng dụng..........................................85 1.3.2. Biên dịch các tập tin nguồn và tạo Stubs và Skeleton...................................85 1.3.3. Tạo các lớp có thể truy xuất từ mạng ............................................................86 1.3.4. Thực thi ng dụng .........................................................................................86 1.3.4. Ví dụ minh họa ..............................................................................................86 1.4. Bài tập áp dụng.....................................................................................................92 Mục lục...............................................................................................................................92 Biên Soạn: Ngô Bá Hùng - Nguyễn Công Huy 96