Giáo trình Lập trình truyền thông (Phần 6)

pdf 10 trang phuongnguyen 2950
Bạn đang xem tài liệu "Giáo trình Lập trình truyền thông (Phần 6)", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfgiao_trinh_lap_trinh_truyen_thong_phan_6.pdf

Nội dung text: Giáo trình Lập trình truyền thông (Phần 6)

  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 Sinh viên thực hiện các bài tập sau 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. o 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
  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 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
  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 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ười ta 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. Hình 3.1 Mô hình ống dẫn Ống dẫn thích hợp cho trường hợp dữ liệu tạo ra của quá trình này sẽ là dữ liệu đầu vào cho quá trình kia. 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: • Ố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. 1.2. Ố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
  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 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
  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. 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
  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 } 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
  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 } } 1.4.5. Biên dịch và thực thi chương trình Biên dịch và thực thi chươ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
  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 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
  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 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
  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 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