JAVA-UDP Socket Programming

Source: Internet
Author: User
Tags message queue

Java Support for UDP

The UDP protocol provides a service that differs from the TCP protocol's end-to-end service, which is non-connected and is unreliable, and UDP sockets do not need to be connected before they are used. In fact, the UDP protocol only implements two functions:

    • The port is added on the basis of IP protocol;
    • Detects data errors that may occur during transmission and discards data that has been corrupted.

Java uses the Datagrampacket class and the Datagramsocket class to use UDP sockets, and both the client and server side send and receive data through the Datagramsocket Send () method and the Receive () method, using Datagra Mpacket to package the data that needs to be sent or received. When sending a message, Java creates a Datagrampacket instance containing the information to be sent and passes it as a parameter to the Send () method of the Datagramsocket instance; When the message is received, the Java program first creates a Datagrampacket instance. The instance allocates some space beforehand, stores the received information in the space, and then passes the instance as a parameter to the receive () method of the Datagramsocket instance. When creating an Datagrampacket instance, be aware that if the instance is used to wrap the data to be received, the remote host and port of the data source are not specified, only a byte array of the cached data can be specified (after the call to receive () method receives the data, Information such as the source address and port is automatically included in the Datagrampacket instance, and if the instance is used to wrap the data to be sent, specify the destination host and port to send to.

Steps to establish a UDP communication

The UDP client first sends a data message to the server that is passively waiting to be contacted. A typical UDP client is going through the following three steps:

    • Create a Datagramsocket instance, you can choose to set the local address and port number, if the port number is set, the client will listen to the port number from the server-side data sent;
    • Use the Send () and receive () Methods of the Datagramsocket instance to send and receive datagrampacket instances for communication;
    • After the communication is complete, call the Close () method of the Datagramsocket instance to close the socket.

Because UDP is not connected, the UDP server does not need to wait for the client's request to establish a connection. In addition, the UDP server uses the same socket for all communications, which is different from the TCP server, and the TCP server creates a new socket for each accept () method that is successfully returned. A typical UDP server is going through the following three steps:

    • Create a Datagramsocket instance, specify the local port number, and optionally specify a local address, at which point the server is ready to receive data packets from any client;
    • Receive a Datagrampacket instance using the Receive () method of the Datagramsocket instance, when the receive () method returns, the data message contains the address of the client, so that the reply message should be sent to where;
    • Use the Send () method of the Datagramsocket instance to return the Datagrampacket instance to the server side.
UDP Socket Demo

Here's one thing to note: The UDP program blocks at the receive () method until it receives a data message or waits for a timeout. Because the UDP protocol is an unreliable protocol, if the datagram is lost during transmission, the program will always block at the receive () method so that the client will never receive the data sent back by the server, but without any hint. To avoid this problem, we use the Datagramsocket class's Setsotimeout () method at the client to develop the maximum blocking time for the receive () method, specifying the number of times the datagram will be re-sent, and if each block times out and the number of postbacks reaches the set limit, The client is closed.

The following shows a client server UDP communication Demo (no multithreading), the client listens to the received data on the local 9000 port, and sends the string "Hello udpserver" to the local server's 3000 port, the service side listens to the received data on the local 3000 port If the data is received, the string "Hello UdpClient" is returned to port 9000 of the client. On the client side, since the program may always block at the receive () method, here we use the Setsotimeout () method of the Datagramsocket instance to specify the maximum blocking time of receive () for the client, and set the number of times to re-send the data. If the data sent back from the server is still not received, we shut down the client.

The client code is as follows:

Package Zyb.org.UDP;  Import java.io.IOException;  Import java.io.InterruptedIOException;  Import Java.net.DatagramPacket;  Import Java.net.DatagramSocket;  Import java.net.InetAddress;  Public classUdpClient {Private StaticFinalintTIMEOUT = the;//set the time-out for receiving data    Private StaticFinalintMaxnum =5;//set the maximum number of times to re-send data     Public Static voidMain (String args[]) throws ioexception{string Str_send="Hello Udpserver"; byte[] buf =New byte[1024x768]; //The client listens to the received data on port 9000Datagramsocket ds =NewDatagramsocket (9000); InetAddress Loc=Inetaddress.getlocalhost (); //defines the Datagrampacket instance used to send dataDatagrampacket dp_send=NewDatagrampacket (Str_send.getbytes (), Str_send.length (), LOC, the); //define a Datagrampacket instance to receive dataDatagrampacket dp_receive =NewDatagrampacket (BUF,1024x768); //data sent to local 3000 portDs.setsotimeout (TIMEOUT);//set the maximum time to block when receiving data        intTries =0;//number of times the data was re-sentBoolean receivedresponse =false;//whether to receive the flag bit of the data//exits the loop until the data is received, or if the number of postbacks reaches a predetermined value         while(!receivedresponse && tries<maxnum) {              //Send Datads.send (dp_send); Try{                  //receive data sent back from the serverds.receive (dp_receive); //throws an exception if the received data does not come from the destination address                if(!dp_receive.getaddress (). Equals (Loc)) {                      Throw NewIOException ("Received Packet from a umknown source"); }                  //If the data is received. Change the RECEIVEDRESPONSE flag bit to True to exit the loopReceivedresponse =true; }Catch(interruptedioexception e) {//if blocking times out when data is received, re-send and reduce the number of times a retry is sentTries + =1; System. out. println ("Time Out ,"+ (maxnum-tries) +"More tries ..." ); }          }          if(receivedresponse) {//If you receive the data, print it outSystem. out. println ("client received data from server:"); String str_receive=NewString (Dp_receive.getdata (),0, Dp_receive.getlength ()) +" from"+ dp_receive.getaddress (). Gethostaddress () +":"+Dp_receive.getport (); System. out. println (str_receive); //since dp_receive receives the data, its internal message length value becomes the number of bytes of the actual received message .//So here we have to reset the internal message length of dp_receive to 1024x768.Dp_receive.setlength (1024x768); }Else{              //If the data sent back by the server is still not received after maxnum the data, print the following informationSystem. out. println ("No Response--Give up.");      } ds.close (); }    }   

The service-side code is as follows:

 PackageZyb.org.UDP; Importjava.io.IOException; ImportJava.net.DatagramPacket; ImportJava.net.DatagramSocket;  Public classUdpserver { Public Static voidMain (string[] args)throwsioexception{String str_send= "Hello UdpClient"; byte[] buf =New byte[1024]; //The server listens to the received data on port 3000Datagramsocket ds =NewDatagramsocket (3000); //receive data sent from the clientDatagrampacket dp_receive =NewDatagrampacket (BUF, 1024); System.out.println ("Server is on,waiting-client to send data ..."); Booleanf =true;  while(f) {//server-side receive data from the clientds.receive (dp_receive); System.out.println ("Server received data from client:"); String str_receive=NewString (Dp_receive.getdata (), 0,dp_receive.getlength ()) + "from" + dp_receive.getaddress (). Gethostad Dress () + ":" +Dp_receive.getport ();              System.out.println (str_receive); //data is launched to the client's port 3000Datagrampacket dp_send=NewDatagrampacket (Str_send.getbytes (), Str_send.length (), dp_receive.getaddress (), 9000);              Ds.send (Dp_send); //since dp_receive receives the data, its internal message length value becomes the number of bytes of the actual received message .//So here we have to reset the internal message length of dp_receive to 1024x768.Dp_receive.setlength (1024);      } ds.close (); }  }  

If the server side is not running, receive () will fail with the result as shown in this case:

If the server is running first and the client is not yet running, the result of the service-side run is as follows:

At this point, if the client is running, the data is sent to the server and the data sent back from the server is accepted, and the result is as follows:

Places to be aware of

A small but important difference between UDP sockets and TCP sockets: The UDP protocol retains the boundary information of the message.

Each receive () Call of the Datagramsocket can receive at most one call to the data sent by the Send () method, and the different receive () method calls will never return the amount of data sent by the same send () method.

When the Write () method is called on the output stream of a TCP socket, all callers know that the data has been copied into a transport buffer, and that the data may have been sent or not delivered, and the UDP protocol does not provide a mechanism to recover from a network error, so Data that may need to be re-transmitted is not cached. This means that when the Send () method call returns, the message has been sent to the underlying transport channel.

The maximum amount of data that can be loaded by a UDP data message is 65,507 bytes of data transmitted at a time.

When a message arrives from the network, the data is stored in a FIFO receive data queue before the data that it contains is returned by the read () method of TCP or the receive () method of UDP. For a TCP socket that has already established a connection, all accepted but not yet transmitted bytes are treated as a sequential sequence of bytes. However, for UDP sockets, the received data may come from different senders, the data accepted by a UDP socket is stored in a message queue, each message is associated with its source address information, and each receive () call returns only one message. If the receive () method is called in a Datagrampacket instance with a buffer size of n, and the first message in the receiving queue is longer than N, the receive () method returns only the first n bytes of the message, and the excess is automatically discarded. And there is no message on the receiving program to lose the hint!

For this reason, the recipient should provide a Datagrampacket instance with sufficient cache space to fully store the message that is the maximum length allowed by the application protocol when the receive () method is called. The maximum amount of data allowed to be transferred in a Datagrampacket instance is 65,507 bytes, which is the maximum data that can be loaded by UDP data packets. Therefore, you can use a cache array of about 65600 bytes to accept the data.

The internal message length value of the datagrampacket is changed after the data is received, becoming the length value of the data actually received.

Each Datagrampacket instance contains an internal message length value whose initial value is the length value of the byte cache array, and once the instance receives the message, the length value becomes the actual length value of the received message, which can be used with the Datagrampacket class's GetLength () method to test. If an application calls the receive () method multiple times with the same Datagrampacket instance, it must explicitly reset its internal message length to the actual length of the buffer before each invocation, lest the accepted data be lost.

For example, in the above procedure, if receiver () on the service side, add the following code:

System.out.println (Dp_receive.getlength ());

The resulting output is: 15, which is the length of the received string data "Hello udpserver".

Datagrampacket's GetData () method always returns the original size of the buffer, ignoring the internal offset and length information for the actual data.

Since Datagrampacket's GetData () method always returns the original size of the buffered array, which is the size specified when the buffer array was first created, the length is 1024 in the program above, so if we want to get the received data, we must intercept the GetData () The array returned by the method contains only the portion of the data received. After the Java1.6, we can use the Arrays.copyofrange () method to achieve the above functions in a single step:

byte [] Destbuf =+ dp_receive.getlength ());

Of course, if you want to convert the received byte array to a string, you can also use the method of the direct new string object in this program:

New+ dp_receive.getlength ());

JAVA-UDP Socket Programming

Contact Us

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.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.