To Standart Protocols - SMTP

User Datagram Protocol (UDP)


 
Апликациите комуникиращи по UDP изпращат и получават напълно независими пакети с информация. За разлика от TCP, те не изграждат point-to-point канална връзка.  Доставянет о на пакета не е гарантирано. Не е гарантиран също така редът на доставяне на пакетите. 

Datagram пакетът представлява независимо съобщение в интернет пространството, чието пристигане не е гарантирано.

Пакетът java.net package съдържа три класа за изпращане и получаване на datagram пакети в мрежата: DatagramSocket, DatagramPacket, и MulticastSocket. 

DatagramSocket - върху сървъра и върху клиента

IPv4 Datagram Format


Header Contents

Version
Version of the IP protocol which determines how to interpret the header. Currently the only permitted values are 4 (0100) or 6 (0110). The header format shown here is valid for IPv4 only.
IHL
Length of header as a number of 32-bit words
Type of service
This field is is often ignored by current routers but is meant to allow traffic to be prioritised (among other things).
Total Length
The length of the entire datagram including header and data: maximum permitted it 65,535 bytes or 64K.
Identification, Flags and Fragment Offset
These values allow datagrams to be fragmented for transmission and reassembled at the destination
Time to live
An integer which is decremented at each router "hop"; supposed to be interpreted as a number of seconds but more often treated as a "hop count". If the value reaches zero the datagram is discarded and an ICMP message is sent to the source host.
Protocol
Identifies the transport-layer protocol which will interpret the Data section. This will typically be TCP or UDP but other values are possible. Protocols are identified by a unique number as listed in an online database at www.iana.org.
Header checksum
This is used to verify the header, and is recomputed at each router hop. This field is left out of IPv6 which relies on the transport layer for verification.
Addresses and Options
These are 32-bit IP addresses which identify the network and host address. Note that IP does not have to specify addresses of any intermediate nodes; this can be left to the router. Routing requirements can also be specified in the Options field, along with options to do with security and debugging.

 Datagram структура и полета в  IPv6

IPv6 Main Header Format

Field Name

Size (bytes)

Description

Version

1/2
(4 bits)

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
(20 bits)

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.

Not all devices and routers may support flow label handling, and use of the field by a source device is entirely optional. Also, the field is still somewhat experimental and may be refined over time.

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.

In simpler terms, this field measures the length of the datagram less the 40 bytes of the main header itself.

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 ioffsetto 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 ioffsetto 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 {
  static final int INPORT = 9090;
  private byte[] buf = new byte[1000];   /*65508 bytes, is the maximum amount of                                 data you can send in a single UDP packet. */
  private DatagramPacket dp = new DatagramPacket(buf, buf.length);
  // Can listen & send on the same socket:
  private DatagramSocket socket;

  public DGServer() {
    try {
      socket = new DatagramSocket(INPORT);
      System.out.println("Server started");
      while(true) {
        // Block until a datagram appears:
        socket.receive(dp);                          //setSoTimeout(ms)
        String rcvd = Dgram.toString(dp) +
          ", from address: " + dp.getAddress() +
          ", port: " + dp.getPort();
 

        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 {
  // Can listen & send on the same socket:
  static final int INPORT = 9090;
  private DatagramSocket s;
  private InetAddress hostAddress;
  private byte[] buf = new byte[1000];
  private DatagramPacket dp = 
    new DatagramPacket(buf, buf.length);
  private int id;

  public DGClient(int identifier) {
    id = identifier;
    try {
      // Auto-assign port number:
      s = new DatagramSocket();
      hostAddress = 
        InetAddress.getByName("localhost");
    } catch(UnknownHostException e) {
      System.err.println("Cannot find host");
      System.exit(1);
    } catch(SocketException e) {
      System.err.println("Can't open socket");
      e.printStackTrace();
      System.exit(1);
    } 
    System.out.println("DGClient starting");
  }

  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;

import java.io.*;
import java.net.*;

public class Copy {
    private final int PORT = 9090;
    private int bfLen = 4096;

    private byte bt[] = new byte[bfLen];
    private int len=0;

    Copy(FileInputStream fi, InetAddress dest, DatagramSocket s)throws IOException{
        int npack=0,tot=0;
        try {
            while((len = fi.read(bt))!=-1){                            //read from disk
                s.send(new DatagramPacket(bt, len, dest, PORT));    //send to server
                try{
                    Thread.sleep(200);    // wait server to write the packet
                }
                catch (InterruptedException ex){ }
                System.out.println("send "+ ++npack+ " total "+ (tot+=len) + " bytes");  // control print
            }
        }
        catch(SocketException e) {
            System.err.println("Can't open socket");
            e.printStackTrace();
            System.exit(2);
        }
        finally{
            if(s != null)s.close();
        }


    }

    public static void main(String arg[]) throws IOException{
        if(arg.length!=2){
            System.out.println("You have to give file name and server as command line parameters");
            System.exit(5);
        }
       
        FileInputStream fi = null;
        try {       
            InetAddress ia = InetAddress.getByName(arg[1]);       
            DatagramSocket s = new DatagramSocket();
           
            System.out.println("copy the file "+arg[0]+" to the "+arg[1]);
           
            fi=new FileInputStream(arg[0]);

            new Copy(fi,ia,s);           
            System.out.println("file "+arg[0]+" is sent to "+arg[1]);
        }
        catch(FileNotFoundException ex){
            System.out.println("The file "+arg[0]+" does not exist");
        }
        catch(UnknownHostException exh){
            System.out.println("The host "+arg[1]+" not found");
        }
        catch(SocketException e) {
            System.err.println("Can't open the socket");
        }
        finally{
            if(fi != null)fi.close();
        }
    }
}
========================================================

Трети пример:

Да се реализира Chat сървър и клиент базирани на  UDP протокол

To Standart Protocols - SMTP