The examples that you have seen so far have used "Transmission Control Protocol" (TCP), also known as "sockets based on data streams." According to the design tenet of the protocol, it has high reliability and can guarantee the data to reach the destination smoothly. In other words, it allows the retransmission of data that is "lost" halfway through a variety of reasons. and the order in which bytes are received is the same as when they come out. Of course, this kind of control and reliability needs to pay a price: TCP has a very high overhead.
There is another protocol, called the User Datagram Protocol (UDP), which does not deliberately pursue packets being sent out completely, nor does it guarantee that they arrive in the same order they were sent. We consider this an "unreliable agreement" (TCP is, of course, a "reliable agreement"). It may sound bad, but because it's so much faster, it often comes in handy. For some applications, such as voice signal transmission, if a small number of packets lost on the halfway, then do not care too much, because the speed of transmission is more important. Most Internet games, such as Diablo, use UDP protocol communication, because the speed of network communication is the decisive factor of the smooth game. You can also think of a timekeeping server, if a message is lost, then really do not have to excessive tension. In addition, some applications may be able to send a UDP message back to the server for later recovery. If there is no response at the right time, the message is lost.
Java's support for datagrams is roughly the same as its support for TCP sockets, but there is an obvious difference. For the datagram, we can place a datagramsocket (datagram socket) in both client and server programs, but unlike ServerSocket, the former does not wait for a request to establish a connection dryly. This is because there is no longer a "connection" and instead a datagram is displayed. Another essential difference is that for a TCP socket, once we have built the connection, we no longer need to care who "speaks" to whom--simply passing data back and forth through the conversation stream. But for the datagram, its packets must know where they came from and where they were going. This means that we have to know the information for each datagram package, otherwise the information will not pass properly.
Datagramsocket is used to send and receive packets, while Datagrampacket contains specific information. When you are ready to receive a data clock, simply provide a buffer to place the received data. When the packet arrives, the Internet address and the port number of the origin of the information are automatically initialized via Datagramsocket. So a datagrampacket builder for receiving datagrams is:
Datagrampacket (buf, Buf.length)
Where the BUF is a byte array. Since BUF is a number group, you may wonder why the builder cannot investigate the length of the array itself. In fact, I feel the same way, the only reason to guess is that C-style programming dictates that the arrays there can't tell us how big it is.
You can reuse the receiving code of datagrams without having to build a new one each time. Every time you use it (regenerate), the data in the buffer will be overwritten.
The maximum capacity of the buffer is limited to the allowable packet size, which is located slightly smaller than 64KB. But in many applications, we would prefer it to be smaller, especially when sending data. The size of the packet you choose depends on your application's specific requirements.
Sending out a data clock, datagrampacket not only need to include formal data, but also include an Internet address and port number to determine its destination. So the builder for the output Datagrampacket is:
Datagrampacket (buf, length, inetaddress, Port)
This time, buf (an array of bytes) already contains the data we want to emit. Length can be buf, but it can be shorter, meaning we just want to emit so many bytes. The other two parameters represent the Internet address to which the packet is to be reached and a target port (note ②) for the target machine.
②: We believe that TCP and UDP ports are independent of each other. That is, you can run a TCP and UDP service program at the same time on port 8080, and there is no conflict between the two.
You might think that two builders created two different objects: one for receiving datagrams and the other for sending them. If it's a good object-oriented design, it's recommended that you create them into two different classes instead of a class with different behaviors (the behavior depends on how we build the object). This may be a serious problem, but fortunately, the use of datagrampacket is fairly simple and we don't need to get tangled up in this issue. This will be clearly explained in the following example. This example is similar to the previous multijabberserver and multijabberclient examples for TCP sockets. Multiple customers send the datagram to the server, which feeds back to the same customer who originally sent the message.
To simplify the task of creating a datagrampacket from a string (or creating a string from a datagrampacket), this example first uses a tool class called Dgram:
//: Dgram.java//A utility class to convert back and forth//Between Strings and datagrampackets. I
Mport java.net.*; public class Dgram {public static Datagrampacket Todatagram (String s, inetaddress destia, int destport) {//D
Eprecated in Java 1.1, but it works:byte[] buf = new Byte[s.length () + 1];
S.getbytes (0, S.length (), buf, 0);
The correct Java 1.1 approach, but it ' s//broken (it truncates the String)://byte[] buf = S.getbytes ();
return new Datagrampacket (buf, Buf.length, Destia, Destport);
public static String toString (Datagrampacket p) {//The Java 1.0 approach://return new String (P.getdata (),
0, 0, p.getlength ());
The Java 1.1 Approach:return new String (P.getdata (), 0, P.getlength ()); }
} ///:~
The first method of the
Dgram takes a string, a inetaddress, and a port number as its own argument, copies the contents of the string to a byte buffer, and then passes the buffer into the Datagrampacket builder. Thus building a datagrampacket. Note the "+1" of the buffer allocation-this is important to prevent truncation phenomena. The GetByte () method of string is a special operation that allows a string containing char to be copied into a byte buffer. The method has now been used "against"; Java 1.1 has a "better" way to do this, but it is blocked as a comment here because it truncates part of the string. So even though we get a "against" message when we compile the program in Java 1.1, its behavior is still correct (the error should be fixed when you read it). The
Dgram.tostring () method also shows the Java 1.0 method and the Java 1.1 method (the two are different because there is a new type of String builder).
The following is the server code for the presentation of the datagram:
: Chatterserver.java//A server that echoes datagrams import java.net.*;
Import java.io.*;
Import java.util.*;
public class Chatterserver {static final int inport = 1711;
Private byte[] buf = new byte[1000];
Private Datagrampacket DP = new Datagrampacket (buf, buf.length);
Can Listen & Send on the same socket:private datagramsocket socket;
Public chatterserver () {try {socket = new Datagramsocket (inport);
System.out.println ("Server started");
while (true) {//block until a datagram Appears:socket.receive (DP);
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"///Received datagram to find out where to//send it back: Datagrampacket echo = Dgram.todatagram (echostring,
Dp.getaddress (), Dp.getport ());
Socket.send (Echo);
The 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 Chatterserver (); }
} ///:~
Chatterserver creates a datagramsocket (datagram socket) to receive messages, rather than creating a new one each time we are ready to receive a new message. This single datagramsocket can be reused. It has a port number because it belongs to the server and the customer must know exactly which address they are sending the datagram to. Although there is a port number, there is no Internet address assigned to it, because it resides in the "This" machine, so you know what your Internet address is (currently the default localhost). In an infinite while loop, a socket is told to receive data (receive ()). Then suspend until a datagram appears, and then feedback it back to our desired recipient,--datagrampacket dp--. The packet (Packet) is converted into a string, and the source of the packet's origin Internet address and socket are inserted. This information is displayed, and then an additional string is added to indicate that you have returned from the server feedback.
You may find it a little confusing. As you will see, many different Internet addresses and port numbers may be the origin of the message--in other words, the client may reside in any machine (in this case, they all reside in the localhost, but each customer uses a different port number). In order to send a message back to its real originating client, you need to know the client's Internet address and port number. Luckily, all of this information has been very thoroughly encapsulated inside the message datagrampacket, so all we have to do is take them out with getaddress () and Getport (). Using this information, you can build Datagrampacket echo--it is sent back by the same socket as received. In addition, once the sockets issue datagrams, the Internet address and port information of the "This" machine is added, so when the customer receives the message, it can use GetAddress () and Getport () to understand where the datagram comes from. In fact, the only thing that getaddress () and Getport () could not tell us where the datagram came from was that we created a datagram to be sent and called getaddress () and Getport () before it was officially issued. When the datagram is officially sent, the address and port of the machine are written to the datagram. So we've got the important principle of using the data to get out of the way: no need to track the source of a message! Because it must be kept in the datagram. In fact, the most reliable way for a program is not to try to track it, but to extract the address and port information from the target datagram anyway (as we do here).
To test whether the server is functioning properly, the following program creates a large number of customers (threads) that send packets to the server and wait for the server to feed them back.
: Chatterserver.java//A server that echoes datagrams import java.net.*;
Import java.io.*;
Import java.util.*;
public class Chatterserver {static final int inport = 1711;
Private byte[] buf = new byte[1000];
Private Datagrampacket DP = new Datagrampacket (buf, buf.length);
Can Listen & Send on the same socket:private datagramsocket socket;
Public chatterserver () {try {socket = new Datagramsocket (inport);
System.out.println ("Server started");
while (true) {//block until a datagram Appears:socket.receive (DP);
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"///Received datagram to find out where to//send it back: Datagrampacket echo = Dgram.todatagram (echostring,
Dp.getaddress (), Dp.getport ());
Socket.send (Echo);
The 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 Chatterserver (); }
} ///:~
Chatterclient is created as a thread, so multiple customers can be used to "harass" the server. As you can see, the datagrampacket used for the reception is similar to the one used for Chatterserver. In the builder, the Datagrampacket is created without any parameters (arguments), because it does not need to explicitly indicate which particular numbered port it is in. The Internet address used for this socket will become "this machine" (such as localhost), and the port number will be assigned automatically, as can be seen from the output. Like the one used for the server, this datagrampacket will be used for both sending and receiving.
Hostaddress is the Internet address of the machine that we want to communicate with. In a program, if you need to create a datagrampacket to be outgoing, you must know an accurate Internet address and port number. To be sure, the host must be on a known address and port number so that the client can initiate a "session" with the host.
Each thread has its own unique identification number (although the port number that is automatically assigned to the thread will also provide a unique identifier). In run (), we create a string message that contains the ID number of the thread and the message number that the thread is prepared to send. We use this string to create a datagram that is sent to the specified address on the host, and the port number is obtained directly from a constant within the chatterserver. Once the message is sent, receive () is temporarily blocked until the server replies to the message. All the information attached to the message enables us to know that what goes back to this particular thread is delivered from the originating message. In this example, although it is an "unreliable" protocol, it is still possible to check whether datagrams have gone where they should go (this is true in the localhost and LAN environments, but there may be some errors in non-local connections).
When you run the program, you will find that each thread will end. This means that every datagram packet sent to the server will turn back and feedback to the correct receiver. If this is not the case, one or more threads will hang and enter the "blocked" state until their input is exposed.
You might think that the only way to upload files from one machine to another is through a TCP socket because they are "reliable." However, because the datagram is very fast, so it is a better choice. All we need to do is split the file into multiple datagrams and number each package. Receivers take these packets and reassemble them, and a "header package" tells the machine how many packets it should receive and other important information needed to assemble it. If a package is "lost" halfway, the receiving machine returns a datagram telling the sender to retransmit.