The out-of-order and packet loss of Java Datagram-general Linux technology-Linux programming and kernel information. The following is a detailed description. Accustomed to TCP programming, it is wrong to think that UDP can handle these problems. A udp application must take full responsibility for reliability, including packet loss, duplication, latency, out-of-order, and connection failure.
Generally, we develop and test on a LAN with good reliability and low transmission latency. Some problems are not easy to expose, but errors may occur on the large Internet.
The UDP protocol pushes the responsibility for delivery reliability to the upper layer, that is, the application layer. below, several classes are compiled to specifically deal with two problems: out-of-order and packet loss.
Four classes: DataPacket class, PacketHeader class, PacketBody class, And DataEntry class, which are located in the same file DataPacket. java.
The DataPacket class is equivalent to a facade mode and is provided for external use. Communication Data is also processed in this class.
Public class DataPacket {
InputStream is;
OutputStream OS;
PacketHeader;
PacketBody body;
ArrayList al;
Public static final int DataSwapSize = 64532;
/**
* Used to receive a Datagram
*/
Public DataPacket (){
Header = new PacketHeader ();
Body = new PacketBody ();
Al = new ArrayList ();
}
/**
* Used to send data reports. It calls the message segmentation operation.
* @ Param file String hard drive file
*/
Public DataPacket (String file ){
This ();
Try {
Is = new FileInputStream (file );
Header. CalcHeaderInfo (is. available ());
This. madeBody ();
Is. close ();
// This. Gereratedata ();
}
Catch (FileNotFoundException ex ){
Ex. printStackTrace ();
}
Catch (IOException ex1 ){
Ex1.printStackTrace ();
}
}
/**
* Used to send data reports. It calls the message segmentation operation.
* @ Param url URL
*/
Public DataPacket (URL url ){
This ();
Try {
// Is = url. openStream ();
URLConnection conn = url. openConnection ();
Is = conn. getInputStream ();
Int total = conn. getContentLength ();
Header. CalcHeaderInfo (total );
This. madeBody ();
// System. out. println (total + ":" + total );
Is. close ();
}
Catch (IOException ex ){
Ex. printStackTrace ();
}
}
/**
* For the sending construction group, the PackageHeader is used to process the Header Format and serial number of the grouping.
*/
Private void madeBody (){
Al. clear ();
Byte [] buffer;
DataEntry de;
For (int I = 0; I Try {
ByteArrayOutputStream bos = new ByteArrayOutputStream ();
// Is. skip (I * body. BODY_BUFFER_SIZE );
Header. ArrageSort (I );
De = new DataEntry (PacketBody. BODY_BUFFER_SIZE );
De. setSn (I );
De. setStreamsize (header. getStreamsize ());
De. setFragmentcounter (header. getFragmentcounter ());
If (header. isWTailFragment (I )){
Buffer = new byte [header. getMinfragment ()];
Is. read (buffer, 0, buffer. length );
Header. setActByteSize (header. getMinfragment ());
De. setActByteSize (header. getMinfragment ());
}
Else {
Buffer = new byte [body. BODY_BUFFER_SIZE];
Is. read (buffer, 0, buffer. length );
}
// System. out. println ("length -------" + I + "" + body. getBody (). length + "" + header. getMinfragment ());
Body. setBody (buffer );
// System. out. println ("length:" + I + "" + header. toString ());
Bos. write (header. getByte (), 0, header. HEADER_BUFFER_SIZE );
Bos. write (body. getBody (), 0, body. getBody (). length );
De. setBytes (bos. toByteArray ());
Al. add (de );
}
Catch (IOException ex ){
Ex. printStackTrace ();
}
}
}
/**
* Creates a group for sending. the header format is not taken into account and no serial number is produced for the grouping.
*/
Private void madeBody1 (){
Al. clear ();
For (int I = 0; I Try {
If (header. isWTailFragment (I ))
Is. read (body. getBody (), I * body. BODY_BUFFER_SIZE,
Header. getMinfragment ());
Else
Is. read (body. getBody (), I * body. BODY_BUFFER_SIZE,
Body. BODY_BUFFER_SIZE );
ByteArrayOutputStream bos = new ByteArrayOutputStream ();
Bos. write (header. getByte (), 0, header. HEADER_BUFFER_SIZE );
Bos. write (body. getBody (), header. HEADER_BUFFER_SIZE,
Body. getBody (). length );
Al. add (bos );
}
Catch (IOException ex ){
Ex. printStackTrace ();
}
}
}
/**
* After receiving a packet, the packet is assembled to handle packet loss and out-of-order.
* @ Param b1 byte []
*/
Public void Add (byte [] b1 ){
Byte [] buffer = (byte []) b1.clone ();
HandlerText (buffer );
DataEntry de = new DataEntry (buffer, header. getActByteSize ());
De. setSn (header. getSn ());
De. setStreamsize (header. getStreamsize ());
De. setFragmentcounter (header. getFragmentcounter ());
Al. add (de );
}
Private void handlerText (byte [] buffer ){
ByteArrayOutputStream baos = new ByteArrayOutputStream ();
Baos. write (buffer, 0, header. HEADER_BUFFER_SIZE );
Byte [] B = new byte [header. HEADER_BUFFER_SIZE];
System. arraycopy (buffer, 0, B, 0, B. length );
ByteArrayInputStream bais = new ByteArrayInputStream (baos. toByteArray ());
InputStreamReader isr = new InputStreamReader (bais );
BufferedReader br = new BufferedReader (isr );
Try {
Header = new PacketHeader (br. readLine ());
}
Catch (Exception ex ){
Ex. printStackTrace ();
}
}
Public ArrayList getDataPackets (){
Return al;
}
/**
* Whether the receipt is complete, determined by whether the serial number is equal to the maximum segment number. This may be a problem. For example, the last segment is lost.
* The entire package is lost.
* @ Return
*/
Public boolean isFull (){
Return this. header. getSn () = this. header. getFragmentcounter ()-1? True: false;
}
/**
* Judge whether there is only one segment.
* @ Return
*/
Public boolean isZero (){
Return this. header. getSn () = 0? True: false;
}
/**
* This function executes Message Assembly, regardless of the lost message.
* @ Return
*/
Private ByteArrayOutputStream fetchDataPackets (){
ByteArrayOutputStream bos = new ByteArrayOutputStream ();
Byte [] buffer = null;
DataEntry de;
For (int I = 0; I <al. size (); I ++ ){
Try {
De = this. getSnData (I );
Buffer = de. getByte ();
If (header. getStreamsize () = de. getStreamsize ()){
Bos. write (de. getByte (), header. HEADER_BUFFER_SIZE, de. getActByteSize ());
System. out. println (de. toString () + "-- fetchDataPackets ");
}
}
Catch (Exception ex ){
Ex. printStackTrace ();
}
}
Return bos;
}
/**
* This function is used to assemble messages. For lost messages, empty messages are written.
* @ Return ByteArrayOutputStream
*/
Private ByteArrayOutputStream fetchDataPackets_sn (){
ByteArrayOutputStream bos = new ByteArrayOutputStream ();
Byte [] buffer;
DataEntry de;
For (int I = 0; I Try {
De = this. getSnData (I );
If (de = null ){
De = seachDeData (I );
}
Buffer = de. getByte ();
// System. out. println (de. getSn () + ":" + I );
// HandlerText (buffer );
// Bos. write (buffer, header. HEADER_BUFFER_SIZE,
// Buffer. length-header. HEADER_BUFFER_SIZE );
If (header. getStreamsize () = de. getStreamsize ()){
Bos. write (de. getByte (), header. HEADER_BUFFER_SIZE,
De. getActByteSize ());
// System. out. println (de. toString ());
}
}
Catch (Exception ex ){
Ex. printStackTrace ();
}
}
Return bos;
}
/**
* Sort the buffered data packets, that is, extract data of the same frame in sequence. If no frame of the serial number is found, a null value is returned.
* @ Param sn int indicates the sequence number of the frame to be searched.
* @ Return DataEntry
*/
Private DataEntry getSnData (int sn ){
DataEntry de = null;
For (int I = 0; I <al. size (); I ++ ){
De = (DataEntry) al. get (I );
If (header. getStreamsize () = de. getStreamsize ()){
If (sn = de. getSn ())
Break;
Else
De = null;
}
}
Return de;
}
/**
* Start to search for the nearest frame segment forward or backward by sequence number. In the future, you can add the request resend function to enable a communication connection.
* @ Param sn int
* @ Return DataEntry
*/
Private DataEntry seachDeData (int sn ){
DataEntry de = null;
Int initvalue, minvalue = 10000;
DataEntry back, fore = null;
For (int I = 0; I <al. size (); I ++ ){
De = (DataEntry) al. get (I );
If (header. getStreamsize () = de. getStreamsize ()){
Initvalue = Math. abs (de. getSn ()-sn );
If (de. getFragmentcounter ()! = De. getSn () & initvalue <minvalue ){
Minvalue = initvalue;
Fore = de;
}
}
}
Return fore;
}
/**
* Except the last frame, one frame is randomly selected.
* @ Return DataEntry
*/
Private DataEntry seachDeData (){
DataEntry de = null;
For (int I = 0; I <al. size (); I ++ ){
De = (DataEntry) al. get (I );
System. out. println ("sky:" + de. getFragmentcounter () + ":" + de. getSn () +
":" + I );
If (header. getStreamsize () = de. getStreamsize ()){
If (de. getFragmentcounter ()! = De. getSn ()){
Break;
}
}
}
Return de;
}
/**
* Generate the assembled result data. Because the image is used for testing, it is returned to the image.
* @ Return Image
*/
Public java. awt. Image Gereratedata (){
ByteArrayInputStream bis;
Java. awt. image. BufferedImage bimage = null;
Try {
Byte [] B = fetchDataPackets_sn (). toByteArray ();
// FetchDataPackets_old1 ()
Bis = new ByteArrayInputStream (B );
Bimage = javax. imageio. ImageIO. read (bis );
Public static void main (String args []) {
DataPacket dp = new DataPacket ("e: \ nature \ 14.jpg ");
}
}
/**
* The data entity acts as a temporary processing place.
* @ Author Administrator
*
*/
Class DataEntry {
Byte [] bytes;
Int fragmentcounter, sn, actbytesize;
Long streamsize;
Int minfragment;
Public DataEntry (){
}
Public DataEntry (int size ){
This. actbytesize = size;
}
Public DataEntry (byte [] B, int I ){
This. bytes = B;
This. actbytesize = I;
}
Public byte [] getByte (){
Return this. bytes;
}
Public void setBytes (byte [] B ){
This. bytes = B;
}
/**
* Generate a data header Based on the sequence of file segments.
* @ Param sn file Sequence
*/
Public void ArrageSort (int sn ){
This. setSn (sn );
This. setByte ();
}
Public void CalcHeaderInfo (long l ){
This. setStreamsize (l );
CalcHeaderInfo ();
}
/**
* Calculate the number of segments to be divided into and obtain the minimum margin.
*/
Public void CalcHeaderInfo (){
Fragmentcounter = Math. round (float) streamsize/
PacketBody. BODY_BUFFER_SIZE );
Float critical = (float) streamsize/PacketBody. BODY_BUFFER_SIZE;
If (critical-fragmentcounter <0.5 & critical-fragmentcounter> 0)
Fragmentcounter ++;
Minfragment = (int) (streamsize % PacketBody. BODY_BUFFER_SIZE );
}
Public byte [] getHeader (){
Long it = new Long (this. streamsize );
Return new byte [] {it. byteValue ()};
}
Public byte [] getByte (){
Return header; // this. toString (). getBytes ();
}
/**
* Generate a header byte. First, obtain the size of the header stream: number of segments: Segment sequence: bytes of the actual size of the segment,
* Add the carriage return newline character. For the remaining part of the 1024 bytes, the array of bytes whose element is 0 will be written.
*/
Public void setByte (){
ByteArrayOutputStream bos = new ByteArrayOutputStream ();
Byte [] buffer = this. toByte ();
Try {
Bos. write (buffer );
Bos. write ("\ r \ n". getBytes ());
Bos. write (new byte [PacketHeader. HEADER_BUFFER_SIZE-buffer. length], 0,
PacketHeader. HEADER_BUFFER_SIZE-buffer. length );
Header = bos. toByteArray ();
}
Catch (IOException ex ){
Ex. printStackTrace ();
}
}
Public int getActByteSize (){
Return actbytesize;
}
/**
* The format of the data packet header is: stream size: number of segments: Segment sequence: actual segment size
* The length of the header byte can be changed. For example, you can add the specific information of the stream, such as the name of the file to which the stream belongs, the file type, and other information.
* @ Return String
*/
Public String toString (){
Return streamsize + ":" + this. fragmentcounter + ":" + this. getSn () +
":" + This. getActByteSize ();
}
Public byte [] toByte (){
Return this. toString (). getBytes ();
}
/**
* Is it a tail segment?
* @ Param I int
* @ Return boolean
*/
Public boolean isWTailFragment (int I ){
Return (I = fragmentcounter-1 )? True: false;
}
}
/**
* User Data Zone
* @ Author Administrator
*
*/
Class PacketBody implements Serializable {
Public static final int BODY_BUFFER_SIZE = 63508; // 65508
Byte [] body;
Public PacketBody (){
}
Public void setBody (byte [] B ){
This. body = B;
}
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.