Xem mẫu
- 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;
- }
}
}
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ủ.
- + 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
- 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);
- 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();
- // 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();
- }
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();
- 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
- 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.*;
- 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();
- }
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();
- 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);
- + 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.
- 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.
- 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.
- 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
- 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
- Để 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:
- 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ề.
- //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