【发布时间】:2016-04-19 20:24:28
【问题描述】:
我正在完成使用 java 使 UDP 可靠的任务。如何添加超时和重新传输来处理被丢弃的数据报并添加序列号,以便客户端可以验证回复是否针对适当的请求??
这是客户端代码
import java.net.*;
import java.io.*;
public class EchoClient {
// UDP port to which service is bound
public static final int SERVICE_PORT = 7;
// Max size of packet
public static final int BUFSIZE = 256;
public static void main(String args[]){
if (args.length != 1)
{
System.err.println ("Syntax - java EchoClient hostname");
return;
}
String hostname = args[0];
// Get an InetAddress for the specified hostname
InetAddress addr = null;
try
{
// Resolve the hostname to an InetAddr
addr = InetAddress.getByName(hostname);
}
catch (UnknownHostException uhe)
{
System.err.println ("Unable to resolve host");
return;
}
try
{
// Bind to any free port
DatagramSocket socket = new DatagramSocket();
// Set a timeout value of two seconds
socket.setSoTimeout (2 * 1000);
for (int i = 1 ; i <= 10; i++)
{
// Copy some data to our packet
String message = "Packet number " + i ;
char[] cArray = message.toCharArray();
byte[] sendbuf = new byte[cArray.length];
for (int offset = 0; offset < cArray.length ; offset++)
{
sendbuf[offset] = (byte) cArray[offset];
}
// Create a packet to send to the UDP server
DatagramPacket sendPacket = new DatagramPacket(sendbuf, cArray.length, addr, SERVICE_PORT);
System.out.println ("Sending packet to " + hostname);
// Send the packet
socket.send (sendPacket);
System.out.print ("Waiting for packet.... ");
// Create a small packet for receiving UDP packets
byte[] recbuf = new byte[BUFSIZE];
DatagramPacket receivePacket = new DatagramPacket(recbuf, BUFSIZE);
// Declare a timeout flag
boolean timeout = false;
// Catch any InterruptedIOException that is thrown
// while waiting to receive a UDP packet
try
{
socket.receive (receivePacket);
}
catch (InterruptedIOException ioe)
{
timeout = true;
}
if (!timeout)
{
System.out.println ("packet received!");
System.out.println ("Details : " + receivePacket.getAddress() );
// Obtain a byte input stream to read the UDP packet
ByteArrayInputStream bin = new ByteArrayInputStream (
receivePacket.getData(), 0, receivePacket.getLength() );
// Connect a reader for easier access
BufferedReader reader = new BufferedReader (
new InputStreamReader ( bin ) );
// Loop indefinitely
for (;;)
{
String line = reader.readLine();
// Check for end of data
if (line == null)
break;
else
System.out.println (line);
}
}
else
{
System.out.println ("packet lost!");
}
// Sleep for a second, to allow user to see packet
try
{
Thread.sleep(1000);
}catch (InterruptedException ie) {}
}
}
catch (IOException ioe)
{
System.err.println ("Socket error " + ioe);
}
}
}
【问题讨论】:
-
UDP 被专门设置为不可靠。另一方面,TCP 被构建为可靠的。所以如果你想要可靠,你应该使用TCP
-
@ControlAltDel 这并不完全正确。人们经常通过在 UDP 之上创建自己的服务来利用 UDP 的性能提升。
-
这很好,但我们可以向客户端添加一些功能以使其可靠,例如校验和或序列号和超时
-
@flkes 我认为 ControlAltDel 是正确的,人们确实创建了像 UDP 这样的协议,但 UDP 本身被设计为不可靠的。 UDP没有选项头,意味着客户端和服务器端没有空间添加序列号、缓冲区和窗口支持,这三个头是使TCP可靠的主要因素。
-
@M.N.N,我认为您不能添加它们,因为 UDP 没有空间让您添加额外的标头。您可以在两侧添加缓冲区或创建窗口,但只能在一定程度上提高可靠性。
标签: java