Xem mẫu

  1. 1. Internet Address Java xây dựng một lớp InetAddress dành riêng cho việc quản lý địa chỉ theo tên và theo số. Lớp InetAddress cung cấp các phương thức static thông dụng nhất dùng để chuyển đổi và truy xuất địa chỉ IP (không có phương thức khởi dựng cho lớp này). Thường ta sẽ quan tâm đến các phương thức sau: +) public static InetAddress getLocalHost () throw UnknownHostExceptiongetByName Trả về đối tượng InetAddress là địa chỉ của máy cục bộ (localhost) Ví dụ: InetAddress host=InetAddress.getLocalHost(); +) public static InetAddress getByName (String host) throws UnknownHostException Phương thức này nhận một địa chỉ của một máy bằng kiểu chuỗi String và trả về đối tượng kiểu InetAddress thay mặt cho địa chỉ máy này. Ví dụ: InetAddress host=InetAddress.getByName(“203.162.10.100”); InetAddress host=InetAddress.getByName(“www.mobifone.com.vn”); +) public static InetAddress[] getAllByName(String host) throws UnknownHostException Phương thức này nhận một địa chỉ của một máy bằng kiểu chuỗi và trả về tất cả các đối tượng InetAddress thay mặt cho địa chỉ máy này. +) public byte [] getAddress () Trả về địa chỉ IP của đối tượng InetAddrees dưới dạng một dãy các byte. Vị trí byte cao nhất nằm ở byte 0 +) public String getHostAddrees () Trả về địa chỉ IP của đối tượng InetAddrees dưới dạng một chuỗi được định dạng phân làm 4 nhóm %d.%d.%d.%d (ví dụ "172.16.9.35"). Ví dụ: Cho cấp thấp dùng lớp InetAddrres để lấy về các thông tin của địa chỉ máy chủ. import java.net.*; public class AddrLookupApp { public static void main(String args[]) { Try { if(args.length!=1) { System.out.println("Usage: java AddrLookupApp "); return; } /* Lấy về đối tượng InetAddress chứa thông tin địa chỉ máy chủ */ InetAddress host=InetAddress.getByName(args[0]); //Lấy địa chỉ IP String hostName = host.getHostName(); //Lấy tên Host /* Xuất các thông tin ra màn hình */ System.out.println("Host name: "+hostName); //Xuất tên Host System.out.println("IP address:" + host.getHostAddress()); //Xuất địa chỉ IP }catch(UnknownHostException e) { System.out.println("Address not found"); return;
  2. } } } Kết quả: Nếu máy tính của ta có kết nối trực tiếp với Internet ta có thể chạy chương trình này để lấy về địa chỉ của những máy chủ nổi tiếng như : C:\JavaNet>java AddrLookupApp java.sun.com Host name : java.sun.com //Tên Host IP addrees : 192.9.9.100 //Địa chỉ IP 2. Lập trình Socket 2.1. Socket Lớp Socket dùng tạo kết nối từ phía máy khách với máy chủ. Thường được khởi dựng bằng các phương thức sau: - Các hàm khởi tạo của lớp Socket + public Socket (String host, int port) throws UnknownHostException, IOException Tạo ra một socket kết nối máy tính có tên theo địa chỉ host + public Socket (InetAddress address, int port) throws IOException Tạo ra một socket kết nối từ địc chỉ là đối tượng InetAddress vào số cổng +) public Socket(String host, int port, boolean stream) throws IOExceptionpublic Tạo ra một socket kết nối theo địa chỉ host và số cổng, tham số stream cuối cùng để quy định kết nối theo TCP (stream=true) hay UDP (stream = false). Tuy nhiên nếu áp dụng để tạo socket cho giao thức UDP nên sử dụng lớp thay thế là DatagramSocket. + public Socket (String host, int port, InetAddress localaddr, int localPort) throws IOException + public Socket (InetAddress addr, int localport, boolean b ) throws IOException - Các phương thức thao tác trên Socket + public InputStream getInputStream() throws IOException + public OutputStream getOutputStream() throws IOException + public void close() throws IOException 2.2. ServerSocket. Lớp ServerSocket dùng kết nối từ phía máy chủ với các máy khách. Ðối tượng ServerSocket được tạo ra trên máy chủ và lắng nghe những kết nối từ phía máy khách gửi đến theo một số cổng định trước. Ðối tượng ServerSocket được khởi dựng từ phương thức sau: - Các hàm khởi tạo của lớp ServerSocket + public ServerSocket (int port)throws IOException + public ServerSocket (int port, int count)throws IOException + public ServerSocket (int port, int count, InetAddr localaddr)throws IOException port là số hiệu cổng mà đối tượng ServerSocket phải lắng nghe để nhận biết những kết nối từ phía máy khách gửi đến. - Các phương thức thao tác trên ServerSocket + public Socket accept() throws IOException Phương thức này thực sự dừng lại chờ đợi cho đến khi nhận được thông tin kết nối sẽ trả về đối tượng socket của máy khách nơi có yêu cầu nối với máy chủ.
  3. + public void close() throws IOException Cuối cùng máy chủ có thể cắt đứt mọi kết nối bằng cách gọi phương thức close của đối tượng ServerSocket: 3. Lập trình TCP 3.1. Server - Tạo ServerSocket - Gọi thực thi phương thức accept() để chấp nhận thiết lập kết nối với Client => nhận được Socket giao tiếp với Client. - Lấy InputStream và OutputStream để nhận và gửi dữ liệu với Client. - Gửi và nhận dữ liệu với Client, sử dụng các phương thức read() và write() của các lớp đối tượng InputStream và OutputStream. - Đóng Socket và ServerSocket - Kết thúc chương trình Server TCP ServerSocket ssk = new ServerSocket(1234); Socket sk= ssk.accept(); InputStream is= sk.getInputStream(); OutputStream os= sk.getOutputStream(); byte[] buffer= new byte[128]; int len= is.read(buffer); System.out.println(new String(buffer,0,len)); sk.close(); ssk.close(); 3.2. Client TCP. - Tạo Socket kết nối đến Server - Lấy InputStream và OutputStream để nhận và gửi dữ liệu với Server. - Gửi và nhận dữ liệu với Server, sử dụng các phương thức read() và write() của các lớp đối tượng InputStream và OutputStream. - Đóng Socket - Kết thúc chương trình Client TCP Socket sk = new Socket(“10.0.0.1”, 1234); InputStream is= sk.getInputStream(); OutputStream os= sk.getOutputStream(); String msg=“hello”; os.write(msg.getBytes()); sk.close(); Tóm lại: Gửi nhận Server và Client theo TCP/IP Chương trình ở Server Chương trình ở Client Khai báo Khai báo ServerSocket server = new Socket server =new chờ kết ServerSocket(5000); Socket("127.0.0.1",5000); nối
  4. Nhận DL Socket client =server.accept(); từ bàn phím Nhận DL BufferedReader br=new BufferedReader BufferedReader br=new BufferedReader từ máy (new InputStreamReader(System.in)); (new InputStreamReader(System.in)); khác Dùng để BufferedReader brIn=new BufferedReader brIn=new gửi BufferedReader (new BufferedReader(new DLiệu InputStreamReader(client.getInputStreaInputStreamReader(server.getInputStrea m()));m())); Nhận DataOutputStream dos = new DataOutputStream dos = new DLiêu về DataOutputStream(client.getOutputStreaDataOutputStream m()); (server.getOutputStream()); Gửi String st=brIn.readLine(); String st=brIn.readLine(); DLiêu đi Exception dos.writeBytes(st); dos.writeBytes(st); dos.write(13); dos.write(13); dos.write(10); dos.write(10); dos.fflush(); dos.fflush(); Khai báo IOException UnknownHostException IOException Ví dụ:Xây dựng hai chương trình: một chương trình là Echosever chạy trên máy chủ dùng để lắng nghe kết nối từ phía máy khách và xử lý yêu cầu do máy khách đưa đến, một chương trình khác là Echoclient chạy trên máy khách có nhiệm vụ nhận dữ liệu nhập vào từ bàn phím sau đó gửi đến cho máy chủ xử lý. Khi máy chủ xử lý xong chương trình Echoclient sẽ nhận về và đưa đến kết quả ra màn hình. TcpThreadServer.java import java.net.*; import java.io.*; public class tcpThreadServer { public static void main (String args[]) { try { /* Tao doi tuong ServerSocket dung de lang nghe ket noi tu cac may khach gui den cong 3456 */ ServerSocket server = new ServerSocket(3456);
  5. int localPort = server.getLocalPort(); System.out.println("Echo Server is listening on port "+localPort+"."); // Cho doi ket noi tu may khach /* Luu y: Den day chuong trinh se dung lai va cho cho den khi co ket noi xay ra */ Socket client = server.accept(); /* Co ket noi xay ra. Lay cac thong tin tu may khach va cho in ra man hinh */ String destName = client.getInetAddress().getHostName(); int destPort = client.getPort(); System.out.println("Accepted connection to "+destName+" on port "+destPort+"."); // Lay ve luong nhap de doc du lieu tu may khach gui den. /* Luu y: Ta dua luong nhap vao bo loc luong de chuyen doi thanh luong BufferReader co kha nang doc duoc mot chuoi ky tu bang phuong thuc readLine() */ BufferedReader intStream=new BufferedReader(new InputStreamReader (client.getInputStream())); // Lay ve luong xuat de ghi du lieu gui den may khach DataOutputStream outStream = new DataOutputStream(client.getOutputStream()); // Tao luong de doc du lieu tu ban phim BufferedReader keyboardInput = new BufferedReader(new InputStreamReader(System.in)); // Cho doc va xu ly du lieu do may khach gui den boolean finished = false; do {// Doc mot chuoi ky tu do may khach gui den String inLine = intStream.readLine();
  6. // In chuoi nhan duoc ra man hinh System.out.println("Received data from Client: "+inLine); // So sanh chuoi gui den. Neu la "quit" thi cham dut if(inLine.equalsIgnoreCase("quit")){ finished = true; break;} // Nhap lieu tu ban phim va gui di System.out.print("Input data Send: "); String outLine = keyboardInput.readLine(); // Gui tra ket qua ve cho may khach //for(int i=0;i //outStream.write((byte)outLine.charAt(i)); outStream.writeBytes(outLine); outStream.write(13); outStream.write(10); outStream.flush(); System.out.println("Has been sent to Client: "+outLine); }while(!finished); // Dong luong va cat ket noi intStream.close(); outStream.close(); client.close(); server.close();
  7. } catch (IOException e) { // Neu co loi thi in ra man hinh System.out.println(e);} } } tcpThreadClient.java import java.net.*; import java.io.*; public class tcpThreadClient { public static void main(String args[]) { Socket connection; // Luu giu doi tuong ket noi DataOutputStream out; // Luong dung gui du lieu den may chu BufferedReader in; // Luong dung doc du lieu do may chu gui ve try{ // Tao socket ket noi connection = new Socket("127.0.0.1",3456); // Lay ve luong nhap dung doc du lieu do may chu gui ve in = new BufferedReader(new InputStreamReader (connection.getInputStream())); // Lay ve luong xuat dung gui du lieu den may chu out = new DataOutputStream(connection.getOutputStream()); System.out.println("Connected to server at port 3456."); } catch (Exception e) { // Neu gap loi thi in loi ra man hinh System.out.println(e); return; } // Thiet ke lop lien ket voi may chu va nhan du lieu tu ban phim // Tao luong de doc du lieu tu ban phim BufferedReader keyboardInput = new BufferedReader(new InputStreamReader(System.in)); boolean finished=false; do { try { // nhap va gui du lieu System.out.print("Input data Send: "); System.out.flush(); String sendLine = keyboardInput.readLine();
  8. out.writeBytes(sendLine); out.write(13); out.write(10); out.flush(); System.out.println("Has been send to server: "+sendLine); if(sendLine.equalsIgnoreCase("quit")) { finished=true; break; } //nhan du lieu do may chu xu ly se duoc nhan ve va in ra */ int inByte; String outprint=in.readLine(); System.out.println("Received data from Server : "+outprint); } catch(Exception e) { // Neu co loi xuat nhap thi in loi ra man hinh System.out.println(e); } }while(!finished); // Cat dut ket noi cua doi tuong lien ket Try { connection.close(); } catch(IOException ex) { System.out.println("IO error closing socket"); } } } Bài Tập TCP: Bài tập 1: Viêt chương trình sử lý “đổi chữ thường thàh chữ hoa trên máy Server” (Theo quan điểm thầy Vĩnh) * Phần Server: import java.net.*; import java.io.*; class TCPServer_HOA { public static void main (String[] args) { try { //Khai bao Socket server v?i cong la 500
  9. ServerSocket server = new ServerSocket(5000); //Thong bao cho ket noi(Wait connect) System.out.println("Wait connect!"); //Khai bao cho ket noi Socket client =server.accept(); //Thong bao lay ket noi(Connect Accept!)_Ket noi thanh cong System.out.println("Connect Accept!"); //Nhan Du lieu tu máy Client ve Server BufferedReader brIn=new BufferedReader( new InputStreamReader(client.getInputStream())); //Gui Du lieu tu Server den Client DataOutputStream dos =new DataOutputStream (client.getOutputStream()); //Nhan Du lieu ve String st=brIn.readLine(); //Thong boa nhan Du lieu System.out.println("Chuoi nhan duoc ; //Xuat Du lieu ra man hinh System.out.println(st); //Đổi chữ thường thành chữ HOA st=st.toUpperCase(); //Thong bao gui Du lieu System.out.println("Gui tra chuoi da su ly ; //Xat Du lieu da doi thanh chu HOA ra man hinh System.out.println(st); //Gui Du lieu di dos.writeBytes(st); dos.write(13); dos.write(10); //Tinh chieu dai cua chuoi int i=st.length(); dos.write(i); //Dong ket noi Server server.close(); } catch(IOException ie) { System.out.println(ie); } } } * Phần Client: import java.net.*;
  10. import java.io.*; public class TCPClient_HOA { public static void main (String[] args) { try { //Khai bao Socket server voi may ao la "127.0.0.1" Socket server =new Socket("127.0.0.1",5000); //Nh?n Du lieu tu ban phim BufferedReader br=new BufferedReader (new InputStreamReader(System.in)); //Nhan du lieu tu may Server BufferedReader brIn=new BufferedReader (new InputStreamReader(server.getInputStream())); //Dung de gui Du lieu tu Server den Client DataOutputStream dos = new DataOutputStream(server.getOutputStream()); //Thong bao Nhap chuoi can gui System.out.println("Nhap chuoi can gui ; //Nhan Du lieu ve String st=br.readLine(); //Gui Du lieu di dos.writeBytes(st); dos.write(13); dos.write(10); dos.flush(); //Nhan chuoi da duoc chuyen thanh chu HOA st=brIn.readLine(); //Thong bao chuoi da nhan duoc System.out.println("Chuoi nhan duoc"); //Xuat chuoi ra man hinh System.out.println(st); //Khai bao bien ung voi chieu dai cua chuoi int i=brIn.read(); //Xuat ra man hinh thong bao Do dai cua Chuoi System.out.println("Chieu dai chuoi: " + i); //...... brIn.close(); //.... dos.close(); //Dong ket noi voi Server server.close();
  11. } catch(UnknownHostException e) { System.out.println(e); } catch (IOException ie) { System.out.println(ie); } } } Bài tập 2: Viêt chương trình sử lý “đếm độ dài của chuỗi Server” (ĐH CNTT) * Phần Server: public class TCPServer_Dodai { public static void main(String[] args) { //Nhận dữliệu từ máy Client _không cần thiết BufferedReader bf =new BufferedReader(new InputStreamReader(System.in)); InputStream is = null; OutputStream os = null; ServerSocket ssk = null; Socket sk = null; String str = ""; int len = 0; byte[] buff = new byte[128]; try { ssk = new ServerSocket(1234); sk = ssk.accept(); //nhận kết nối từ client is = sk.getInputStream(); os = sk.getOutputStream(); len = is.read(buff); //nhận dữ liệu từ client (mảng các byte) str = new String(buff, 0, len); str = "Length of string: " + len; //Lấy dộ dài của chuỗi ký tự /*str = str.toUpperCase(); //đổi chuỗi ký tự sang hoa */ os.write(str.getBytes()); //gởi dữ liệu tới client } catch (IOException e) { e.printStackTrace(); } finally { try { if (ssk != null) ssk.close();
  12. if (sk != null) sk.close(); } catch (IOException e) { } } } } * Phần Client: public class TCPClient_Dodai { public static void main(String[] args) { BufferedReader br =new BufferedReader(new InputStreamReader(System.in)); InputStream is = null; OutputStream os = null; Socket sk = null; String str = ""; int len = 0; byte[] buff = new byte[128]; try { sk = new Socket(InetAddress.getByName("localhost"), 1234); is = sk.getInputStream(); os = sk.getOutputStream(); System.out.print("Enter a string: "); str = br.readLine(); os.write(str.getBytes()); len = is.read(buff); str= new String(buff, 0, len); System.out.println(str); } catch (IOException e) { e.printStackTrace(); } finally { try { if (sk != null) sk.close(); } catch (IOException e) {} }; } } 3. Lập trình UDP 3.1. DatagramSocket - UDP là giao thức cho phép gửi/nhận từng gói tin đơn lẻ - Java cung cấp lớp java.net.DatagramSocket để lập trình UDP socket - Các hàm khởi tạo của lớp DatagramSocket + public DatagramSocket(int port) throws SocketException Vd: DatagramSocket socket = new DatagramSocket(3456);
  13. + public DatagramSocket() throws SocketException Vd: DatagramSocket socket = new DatagramSocket(); - Các phương thức thác tác trên DatagramSocket + public void send(DatagramPacket p) throws IOException Vd: socket.send(outDatagram); + public void receive(DatagramPacket p) throws IOException Vd: socket.receive(inDatagram); + public void close() + public int getLocalPort() 3.2. DatagramPacket - Java cung cấp lớp đối tượng DatagramPacket để tạo những gói tin sử dụng cho UDP socket - Các hàm khởi tạo của lớp DatagramPacket + public DatagramPacket (byte[] buffer, int length) + public DatagramPacket (byte[] buffer, int length, InetAddress addr, int port) - Các phương thức thao tác trên gói tin UDP + publicbyte[] getData() + public int getLength() + public InetAddress getAddress() + public int getPort() 1. Tổng quan về giao thức UDP UDP (User Datagram Protocol) là một trong những giao thức cốt lõi của giao thức TCP/IP. Dùng UDP, chương trình trên mạng máy tính có thể gởi những dữ liệu ngắn được gọi là datagram tới máy khác. UDP không cung cấp sự tin cậy và thứ tự truyền nhận mà TCP làm; các gói dữ liệu có thể đến không đúng thứ tự hoặc bị mất mà không có thông báo. Tuy nhiên UDP nhanh và hiệu quả hơn đối với các mục tiêu như kích thước nhỏ và yêu cầu khắt khe về thời gian. Do bản chất không trạng thái của nó nên nó hữu dụng đối với việc trả lời các truy vấn nhỏ với số lượng lớn người yêu cầu. 1.1. Cổng UDP dùng cổng để cho phép các giao tiếp giữa các ứng dụng diễn ra. Cổng dùng 16 bit để đánh địa chỉ, vì vậy số của cổng nằm trong khoản 0 đến • 65.535. Cổng 0 được để dành và không nên sử dụng. Cổng từ 1 đến 1023 được gọi là cổng "well-known" và trên các hệ điều hành tựa • Unix, việc gắn kết tới một trong những cổng này đòi hỏi quyền root. Cổng 1024 đến 49.151 là cổng đã đăng ký. • Cổng từ 49.152 đến 65.535 là các cổng tạm, được dùng chủ yếu bởi client khi • liên lạc với server.
  14. 1.2. Cấu trúc gói UDP là giao thức hướng thông điệp nhỏ nhất của tầng giao vận hiện được mô tả trong RFC 768 của IETF. Trong bộ giao thức TCP/IP, UDP cung cấp một giao diện rất đơn giản giữa tầng mạng bên dưới (thí dụ, IPv4) và tầng phiên làm việc hoặc tầng ứng dụng phía trên. UDP không đảm bảo cho các tầng phía trên thông điệp đã được gửi đi và người gửi cũng không có trạng thái thông điệp UDP một khi đã được gửi (Vì lý do này đôi khi UDP còn được gọi làUnreliable Datagram Protocol). UDP chỉ thêm các thông tin multiplexing và giao dịch. Các loại thông tin tin cậy cho việc truyền dữ liệu nếu cần phải được xây dựng ở các tầng cao hơn. Source port: Trường này xác định cổng của người gửi thông tin và có ý nghĩa nếu muốn nhận thông tin phản hồi từ người nhận. Nếu không dùng đến thì đặt nó bằng 0. Destination port: Trường xác định cổng nhận thông tin, và trường này là cần thiết. Length: Trường có độ dài 16 bit xác định chiều dài của toàn bộ datagram: phần header và dữ liệu. Chiều dài tối thiểu là 8 byte khi gói tin không có dữ liệu, chỉ có header. Checksum: Trường checksum 16 bit dùng cho việc kiểm tra lỗi của phần header và dữ liệu. Phương pháp tính checksum được định nghĩa trong RFC 768. Do thiếu tính tin cậy, các ứng dụng UDP nói chung phải chấp nhận mất mát, lỗi hoặc trùng dữ liệu. Một số ứng dụng như TFTP có nhu cầu phải thêm những kỹ thuật làm tin cậy cơ bản vào tầng ứng dụng. Hầu hết các ứng dụng UDP không cần những kỹ thuật làm tin cậy này và đôi khi nó bị bỏ đi. Streaming media, game trực tuyến và voice over IP (VoIP) là những thí dụ cho các ứng dụng thường dùng UDP. Nếu một ứng dụng đòi hỏi mức độ cao hơn về tính tin cậy, những giao thức như TCP hoặc mã erasure có thể dùng thay. Thiếu những cơ chế kiểm soát tắc nghẽn và kiểm soát luồng, các kỹ thuật dựa trên mạng là cần thiết để giảm nguy hiệu ứng cơ tắc nghẽn dây chuyền do không kiểm soát, tỷ lệ tải UDP cao. Nói cách khác, vì người gởi gói UDP không thể phát hiện tắc nghẽn, các thành phần dựa trên mạng như router dùng hàng đợi gói (packet queueing) hoặc kỹ thuật bỏ gói như là những công cụ để giảm tải của UDP. Giao thức Datagram Congestion Control Protocol (DCCP) được thiết kế như một giải pháp cho vấn đề bằng cách thêm hành vi kiểm soát tắc nghẽn cho thiết bị đầu cuối cho các dòng dữ liệu UDP như streaming media.
  15. Mặc dù tổng lượng lưu thông của UDP trên mạng thường chỉ vài phần trăm, nhưng có nhiều ứng dụng quan trọng dùng UDP, bao gồm DNS, SNMP, DHCP và RIP. Trong Java hỗ trợ lập trình mạng sử dụng giao thức UDP thông qua 2 lớp • java.net.DatagramPacket • java.net.DatagramSocket 2. Lớp DatagramPacket 2.1. Giới thiệu Các datagram UDP đưa rất ít thông tin vào datagram IP. Header UDP chỉ đưa tám byte vào header IP. Header UDP bao gồm số hiệu cổng nguồn và đích, chiều dài của dữ liệu và header UDP, tiếp đến là một checksum tùy chọn. Vì mỗi cổng được biểu diễn bằng hai byte nên tổng số cổng UDP trên một host sẽ là 65536. Chiều dài cũng được biểu diễn bằnghai byte nên số byte trong datagram tối đa sẽ là 65536 trừ đi tám 8 byte dành cho phần thông tin header. Trong Java, một datagram UDP được biểu diễn bởi lớp DatagramPacket: PHP Code: public final class DatagramPacket extends Object Lớp này cung cấp các phương thức để nhận và thiết lập các địa chỉ nguồn, đích từ header IP, nhận và thiết lập các thông tin về cổng nguồn và đích, nhận và thiết lập độ dài dữ liệu.Các trường thông tin còn lại không thể truy nhập được từ mã Java thuần túy.DatagramPacket sử dụng các constructor khác nhau tùy thuộc vào gói tin được sử dụng để gửi hay nhận dữ liệu. 2.2. Constructor 2.2.1. Constructor nhận datagram Hai constructor tạo ra các đối tượng DatagramSocket mới để nhận dữ liệu từ mạng: PHP Code: public DatagramPacket(byte[] b, int length) public DatagramPacket(byte[] b, int offset, int length) Khi một socket nhận một datagram, nó lưu trữ phần dữ liệu của datagram ở trong vùng đệm b bắt đầu tại vị trí b[0] và tiếp tục cho tới khi gói tin được lưu trữ hoàn toàn hoặc cho tới khi lưu trữ hết length byte. Nếu sử dụng constructor thứ hai, thì dữ liệu được lưu trữ bắt đầu từ vị trí b[offset]. Chiều dài của b phải nhỏ hơn hoặc bằng b.length-offset.
  16. PHP Code: Ví du: Xây dựng một datagramPacket để nhận dữ liệu có độ lớn 9999 byte byte b[] = new byte[9999]; DatagramPacket dp = new DatagramPacket(b, b.length); 2.2.2. Constructor gửi các datagram Bốn constructor tạo các đối tượng DatagramPacket mới để gửi dữ liệu trên mạng: PHP Code: public DatagramPacket(byte[] b, int length, InetAddress dc, int port) public DatagramPacket(byte[] b, int offset, int length, InetAddress dc, int port) public DatagramPacket(byte[] b, int length, SocketAddress dc, int port) public DatagramPacket(byte[] b, int offset, int length, SocketAddress dc, int port) Mỗi constructor tạo ra một DatagramPacket mới để được gửi đi tới một host khác. Gói tinđược điền đầy dữ liệu với chiều dài là length byte bắt đầu từ vị trí offset hoặc vị trí 0 nếuoffset không được sử dụng. Ví dụ để gửi đi một xâu ký tự đến một host khác như sau: PHP Code: public static void main(String[] args) { String s = "DEMO UDP- http://www.vi-infotech.com"; byte b[] = s.getBytes(); try { InetAddress id = InetAddress.getByName("www.vi-infotech.com"); int port = 7; DatagramPacket dp = new DatagramPacket(b, b.length, id, port); //Gửi gói tin } catch (Exception e) { System.err.println(e); } } Công việc khó khăn nhất trong việc tạo ra một đối tượng DatagramPacket chính là việcchuyển đổi dữ liệu thành một mảng byte. Đoạn mã trên chuyển đổi một xâu ký tự thànhmột mảng byte để gửi dữ liệu đi 2.3. Các phương thức nhận các thông tin từ DatagramPacket DatagramPacket có sáu phương thức để tìm các phần khác nhau của một datagram: dữ liệu thực sự cộng với một số trường header. Các phương thức này thường được sử dụng cho các datagram nhận được từ mạng
  17. public InetAddress getAddress() Phương thức getAddress() trả về một đối tượng InetAddress chứa địa chỉ IP của host ở xa. Nếu datagram được nhận từ Internet, địa chỉ trả về chính là địa chỉ của máy đã gửi datagram (địa chỉ nguồn). Mặt khác nếu datagram được tạo cục bộ để được gửi tới máy ở xa, phương thức này trả về địa chỉ của host mà datagram được đánh địa chỉ public int getPort() Phương thức getPort() trả về một số nguyên xác định cổng trên host ở xa. Nếu datagramđược nhận từ Internet thì cổng này là cổng trên host đã gửi gói tin đi. public SocketAddress() Phương thức này trả về một đối tượng SocketAddress chứa địa chỉ IP và số hiệu cổng củahost ở xa public byte[] getData() Phương thức getData() trả về một mảng byte chứa dữ liệu từ datagram. Thông thường cần phải chuyển các byte này thành một dạng dữ liệu khác trước khi chương trình xử lý dữ liệu. Một cách để thực hiện điều này là chuyển đổi mảng byte thành một đối tượng String public int getLength() Phương thức getLength() trả về số bytes dữ liệu có trong một datagram public getOffset() Phương thức này trả về vị trí trong mảng được trả về bởi phương thức getData() mà từ đó dữ liệu trong datagram xuất phát Sáu constructor ở trên là đủ để tạo lập ra các datagram. Tuy nhiên, Java cung cấp một số phương thức để thay đổi dữ liệu, địa chỉ của máy ở xa, và cổng trên máy ở xa sau khi datagram đã được tạo ra. Trong một số trường hợp việc sử dụng lại các DatagramPacket đã có sẵn sẽ nhanh hơn việc tạo mới các đối tượng này public void setData(byte[] b, int offset, int length) Phương thức này đưa ra giải pháp để gửi một khối lượng dữ liệu lớn. Thay vì gửi toàn bộ dữ liệu trong mảng, ta có thể gửi dữ liệu trong từng đoạn của mảng tại mỗi thời điểm public void setAddress(InetAddress dc) Phương thức setAddress() Thay đổi địa chỉ của máy mà ta sẽ gửi gói tin tới. Điều này sẽcho phép ta gửi cùng một datagram đến nhiều nơi nhận public void setPort(int port) Phương thức này thay đổi số hiệu cổng gửi tới của gói tin. public void setLength(int length) Phương thức này thay đổi số byte dữ liệu có thể đặt trong vùng đệm. 3. Lớp DatagramSocket
  18. Để gửi hoặc nhận một DatagramPacket, bạn phải mở một DatagramSocket. Trong Java, một datagram socket được tạo ra và được truy xuất thông qua đối tượng DatagramSocket PHP Code: public final class DatagramSocket extends Object Tất cả các datagram được gắn với một cổng cục bộ, cổng này được sử dụng để lắng nghe các datagram đến hoặc được đặt trên các header của các datagram sẽ gửi đi. Nếu ta viết một client thì không cần phải quan tâm đến số hiệu cổng cục bộ là bao nhiêuDatagramSocket được sử dụng để gửi và nhận các gói tin UDP. Nó cung cấp các phươngthức để gửi và nhận các gói tin, cũng như xác định một giá trị timeout khi sử dụng phương pháp vào ra không phong tỏa (non blocking I/O), kiểm tra và sửa đổi kích thước tối đa của gói tin UDP, đóng socket. Các phương thức void close(): đóng một liên kết và giải phóng nó khỏi cổng cục bộ. void connect(InetAddress remote_address, int remote_port) InetAddress getInetAddress():phương thức này trả về địa chỉ remote mà socket kết nối tới, hoặc giá trị null nếu không tồn tại liên kết InetAddress getLocalAddress(): trả về địa chỉ cục bộ Int getSoTimeOut(): trả về giá trị tùy chọn timeout của socket. Giá trị này xác định thời gian mà thao tác đọc sẽ phong tỏa trước khi nó đưa ra ngoại lệ InterruptedException. Ở chế độ mặc định, giá trị này bằng 0, chỉ ra rằng vào rakhông phong tỏa được sử dụng void receive(DatagramPacket dp) throws IOException:phương thức đọc một gói tin UDP và lưu nội dung trong packet xác định void send(DatagramSocket dp) throws IOException:phương thức gửi một gói tin void setSoTimeOut(int timeout): thiết lập giá trị tùy chọn của socket 4. Nhận các gói tin Trước khi một ứng dụng có thể đọc các gói tin UDP được gửi bởi các máy ở xa, nó phải gán một socket với một cổng UDP bằng cách sử dụng DatagramSocket, và tạo ra một DatagramPacket sẽ đóng vai trò như là một bộ chứa cho dữ liệu của gói tin UDP. Khi một ứng dụng muốn đọc các gói tin UDP, nó gọi phương thức DatagramSocket.receive(), phương thức này sao chép gói tin UDP vào một DatagramPacket xác định. Xử lý nội dung nói tin và tiến trình lặp lại khi cần Khi xử lý gói tin ứng dụng phải làm việc trực tiếp với một mảng byte. Tuy nhiên nếu ứng dụng là đọc văn bản thì ta có thể sử dụng các lớp từ gói vào ra để chuyển đổi giữa mảng byte và luồng stream và reader. Bằng cách gắn kết luồng nhập ByteArrayInputStream với nội dung của một datagram và sau đó kết nối với một kiểu luồng khác, khi đó bạn có thể truy xuất tới nội dung của gói UDP một cách dễ dàng PHP Code:
  19. ByteArrayInputStream bis = new ByteArrayInputStream(dp.getData()); DataInputStream dis=new DataInputStream(bis); 5. Gửi các gói tin Lớp DatagramSocket cũng được sử dụng để gửi các gói tin. Khi gửi gói tin, ứng dụng phải tạo ra một DatagramPacket, thiết lập địa chỉ và thông tin cổng, và ghi dữ liệu cần truyềnvào mảng byte. Nếu muốn gửi thông tin phúc đáp thì ta cũng đã biết địa chỉ và số hiệucổng của gói tin nhận được. Mỗi khi gói tin sẵn sàng để gửi, ta sử dụng phương thức send()của lớp DatagramSocket để gửi gói tin đi. 3.3 Lập trình Server UDP - Tạo UDP Socket - Tạo DatagramPacket để nhận dữ liệu - Nhận dữ liệu từ Client. - Đóng UDP Socket - Kết thúc chương trình. Server UDP DatagramSocket dsk= new DatagramSocket(1234); byte[] buffer= new byte[128]; DatagramPacket pk= new DatagramPacket(buffer, 128); dsk.receive(pk); System.out.println(“Client: ” + pk.getAddress() + ”:” + pk.getPort()); System.out.println(new String(buffer, 0, pk.getLength())); dsk.close(); 3.4. Lập trình Client UDP - Tạo UDP Socket - Tạo DatagramPacket để gửi dữ liệu - Gửi dữ liệu đến Server. - Đóng UDP Socket - Kết thúc chương trình. Client UDP DatagramSocket dsk= new DatagramSocket(); String msg= “abc”; InetAddress addr= InetAddress.getByName(“10.0.0.1”); DatagramPacket pk= new DatagramPacket(msg.getBytes(), msg.length(), addr, 1234); dsk.send(pk); dsk.close(); Ví dụ: Dưới đây ta sẽ xây dựng một mô hình khách/chủ (client/server) sử dụng lớp datagramSocket và DatagramPackage để kết nối giao thức UDP. Chương trình udpServer sẽ bind địa chỉ IP của localhostServer và port chỉ định là 2345. và chờ nhận gói gửi đến từ udpClient rùi đảo chuỗi và gửi trả lại client. Chương trình udpClient tạo ra datagramSocket và lấy cổng ngẫu nhiên của hệ thống để bind, sau đó gửi chuỗi nhập từ bàn phím tới udpServer, sau đó chờ nhận chuỗi từ udpServer trả về.
  20. //UdpServer.java import java.net.*; import java.io.*; import java.util.*; public class udpServer { public static void main(String args[]) { try { DatagramSocket socket = new DatagramSocket(2345); String localAddress = InetAddress.getLocalHost().getHostName().trim(); int localPort = socket.getLocalPort(); System.out.print(localAddress+": "); System.out.println("Exchange rate server is" + "listening on port "+localPort+"."); int bufferLength = 256; byte outBuffer[]; byte inBuffer[] = new byte[bufferLength]; DatagramPacket outDatagram; DatagramPacket inDatagram = new DatagramPacket(inBuffer,inBuffer.length); boolean finished = false; do { //nhan du lieu socket.receive(inDatagram); InetAddress destAddress=inDatagram.getAddress(); String destHost=destAddress.getHostName().trim(); int destPort = inDatagram.getPort(); System.out.println("\nReceived a datagram from "+destHost+" at port "+destPort+"."); String data = (new String(inDatagram.getData(),0,inDatagram.getLength ())).trim(); System.out.println("It contained the data: "+data); if(data.equalsIgnoreCase("quit")) {finished=true; break;} //gui du lieu String s = new Date().toString(); s=s+"\n NewYork :"+getNewYorkRate(); s=s+"\n Tokyo :"+getTokyoRate(); s=s+"\n HongKong :"+getHongKongRate(); outBuffer=s.getBytes(); outDatagram = new DatagramPacket (outBuffer,outBuffer.length,destAddress,destPort); socket.send(outDatagram); System.out.println("Sent "+s+" to "+destHost+" at port"+destPort+"."); } while(!finished); }catch (IOException ex){ System.out.println("IOException occurred."); } } private static String getNewYorkRate() { return Double.toString(Math.random()*135); }
nguon tai.lieu . vn