Апликациите комуникиращи по UDP изпращат и получават напълно независими
пакети с информация. За разлика от TCP, те не
изграждат point-to-point канална връзка. Доставянет о на
пакета не е гарантирано. Не е гарантиран също така редът на доставяне
на пакетите.
Datagram пакетът представлява независимо съобщение в интернет пространството, чието пристигане не е гарантирано.
Пакетът java.net package съдържа три класа за изпращане и получаване на datagram пакети в мрежата: DatagramSocket, DatagramPacket, и MulticastSocket.
DatagramSocket - върху сървъра и върху клиентаDatagram структура и полета в IPv6
Field Name |
Size (bytes) |
Description |
Version |
1/2 |
Version: Identifies the version of IP used to generate the datagram. This field is used the same way as in IPv4, except of course that it carries the value 6 (0110 binary). |
Traffic Class |
1 |
Traffic Class: This field replaces the Type Of Service (TOS) field in the IPv4 header. It uses the new Differentiated Services (DS) method defined in RFC 2474. That RFC actually specifies quality of service (QOS) techniques; |
Flow Label |
2 1/2 |
Flow Label: This
large field was created to provide additional support for real-time
datagram delivery and quality of service features. The concept of a flow
is defined in RFC 2460 as a sequence of datagrams sent from a source
device to one or more destination devices. A unique flow label is used
to identify all the datagrams in a particular flow, so that routers
between the source and destination all handle them the same way, to
help ensure uniformity in how the datagrams in the flow are delivered.
For example, if a video stream is being sent across an IP internetwork,
the datagrams containing the stream could be identified with a flow
label to ensure that they are delivered with minimal latency. |
Payload Length |
2 |
Payload Length:
This field replaces the Total Length field from the IPv4
header, but it is used differently. Rather than measuring the length of
the whole datagram, it only contains the number of bytes of the
payload. However, if extension headers are included, their length is
counted here as well. |
Next Header |
1 |
Next Header: This field replaces the Protocol field and has two uses. When a datagram has extension headers, this field specifies the identity of the first extension header, which is the next header in the datagram. When a datagram has just this “main” header and no extension headers, it serves the same purpose as the old IPv4 Protocol field and has the same values, though new numbers are used for IPv6 versions of common protocols. In this case the “next header” is the header of the upper layer message the IPv6 datagram is carrying. |
Hop Limit |
1 |
Hop Limit: This replaces the Time To Live (TTL) field in the IPv4 header; its name better reflects the way that TTL is used in modern networks (since TTL is really used to count hops, not time.) |
Source Address |
16 |
Source Address: The 128-bit IP address of the originator of the datagram. As with IPv4, this is always the device that originally sent the datagram. |
Destination Address |
16 |
Destination Address: The 128-bit IP address of the intended recipient of the datagram; unicast, anycast or multicast. Again, even though devices such as routers may be the intermediate targets of the datagram, this field is always for the ultimate destination. |
Клас DatagramPacket
конструктори:
DatagramPacket(byte[] buf,
int length)
Constructs a
DatagramPacket for
receiving packets of length length . |
DatagramPacket(byte[] buf,
int length, InetAddress address, int port)
Constructs a datagram packet for sending
packets of length
length to the specified port number on
the specified host. |
DatagramPacket(byte[] buf,
int offset, int length)
Constructs a
DatagramPacket for
receiving packets of length length , specifying an offset
into the buffer. |
DatagramPacket(byte[] buf,
int offset, int length, InetAddress address, int port)
Constructs a datagram packet for sending
packets of length
length with offset ioffset to
the specified port number on the specified host. |
DatagramPacket(byte[] buf,
int offset, int length, SocketAddress address)
Constructs a datagram packet for sending
packets of length
length with offset ioffset to
the specified port number on the specified host. |
DatagramPacket(byte[] buf,
int length, SocketAddress address)
Constructs a datagram packet for sending
packets of length
length to the specified port number on
the specified host. |
методи:
InetAddress |
getAddress()
Returns the IP address of the machine to which
this datagram is being sent or from which the datagram was received.
|
byte[] |
getData()
Returns the data buffer.
|
int |
getLength()
Returns the length of the data to be sent or
the length of the data received.
|
int |
getOffset()
Returns the offset of the data to be sent or
the offset of the data received.
|
int |
getPort()
Returns the port number on the remote host to
which this datagram is being sent or from which the datagram was
received.
|
SocketAddress |
getSocketAddress()
Gets the SocketAddress (usually IP address +
port number) of the remote host that this packet is being sent to or is
coming from.
|
void |
setAddress(InetAddress iaddr)
Sets the IP address of the machine to which
this datagram is being sent.
|
void |
setData(byte[] buf)
Set the data buffer for this packet.
|
void |
setData(byte[] buf,
int offset, int length)
Set the data buffer for this packet.
|
void |
setLength(int length)
Set the length for this packet.
|
void |
setPort(int iport)
Sets the port number on the remote host to
which this datagram is being sent.
|
void |
setSocketAddress(SocketAddress address)
Sets the SocketAddress (usually IP address +
port number) of the remote host to which this datagram is being sent.
|
Пример:
1) Помощен инструмент за конвертиране String
-> DatagramPacket
DatagramPacket -> String
import java.net.*;
public class Dgram { public static DatagramPacket toDatagram(String s, InetAddress destIA, int destPort) { byte[] buf = s.getBytes(); return new DatagramPacket(buf, buf.length, destIA, destPort); } public static String toString(DatagramPacket p){ return new String(p.getData(), 0, p.getLength()); } } |
2) Сървър
import java.net.*; import java.io.*; import java.util.*; public class DGServer { public DGServer() { |
System.out.println(rcvd); String echoString = "Echoed: " + rcvd; // Extract the address and port from the // received datagram to find out where to // send it back: DatagramPacket echo = Dgram.toDatagram(echoString, dp.getAddress(), dp.getPort()); socket.send(echo); } } catch(SocketException e) { System.err.println("Can't open socket"); System.exit(1); } catch(IOException e) { System.err.println("Communication error"); e.printStackTrace(); } } public static void main(String[] args) { new DGServer(); } } |
3) Клиент
import java.net.*; import java.io.*; public class DGClient extends Thread {
public DGClient(int identifier) {
|
public void run() { try { for(int i = 0; i < 25; i++) { String outMessage = "Client #" + id + ", message #" + i; // Make and send a datagram: s.send(Dgram.toDatagram(outMessage, hostAddress, INPORT)); // Block until it echoes back: s.receive(dp); // Print out the echoed contents: String rcvd = "Client #" + id + ", rcvd from " + dp.getAddress() + ", " + dp.getPort() + ": " + Dgram.toString(dp); System.out.println(rcvd); } } catch(IOException e) { e.printStackTrace(); System.exit(1); } } public static void main(String[] args) { for(int i = 0; i < 10; i++) new DGClient(i).start(); } } |
Втори пример:
На базата на примера за копиране на бинарен файл да се направи приложение, базирано на UDP протокол, което прехвърля бинарен файл между два компютъра .
Клиента и сървъра са разположени в два различни пакета. Клиентът е активната страна, която прехвърла файла към сървъра. Програмата изисква въвеждането на два параметръра на командната линия - име на файла и адрес на сървъра. Пакетите са с предварително уточнена дължина. Сървъра работи на порт 9090, а клиентът - на анонимен порт. Клиентът чете в цикъл порции от файла в буфер, подготвя datagram пакет и го прехвърля на сървъра, (като изчаква по 200 мс след всеки пакет за да даде възможност на сървъра да го запише и да не допусне натрупване и загуба на пакети). Цикълът продължава до изчитане на файла. Сървърът чете всеки пакет и го записва във файл d:\\Test\\server\\up.jpg. Критерий за край на програмата е получаването на последния по-къс пакет от клиента.
UDP server
====================================================
package server;
import java.io.*;
import java.net.*;
public class Server {
private final int
INPORT = 9090;
private int bfLen
= 4096;
private
DatagramSocket s=null;
private byte[] buf
= new byte[bfLen];
private
FileOutputStream fo = null;
private
DatagramPacket dp=new DatagramPacket(buf, buf.length);
Server() throws
IOException{
int npack=0, total=0;
String fname = "d:\\Test\\server\\up.jpg";
try {
s= new DatagramSocket(INPORT);
System.out.println("Server started");
fo = new FileOutputStream(fname);
do{
s.receive(dp);
System.out.println("receive "+
++npack+ " total: "+ (total+=dp.getLength())+"\t"+dp.getLength());
// control print
fo.write(dp.getData(),0,dp.getLength());
}while(dp.getLength()==bfLen);
}
catch(SocketException e) {
System.err.println("Can't open the socket");
e.printStackTrace();
System.exit(2);
}
catch(FileNotFoundException exf){
System.err.println("Can't create the file "+ fname);
}
finally{
if(s != null)s.close();
if(fo != null)fo.close();
}
System.out.println("File received");
}
public static void
main(String arg[]) throws IOException{
new Server();
}
}
===================================================
Клиент:
=======================================================
package client;
Трети пример:
Да се реализира Chat сървър и клиент базирани на UDP протокол