我会直接上去,这是与家庭作业相关的,但是家庭作业是关于使用UDP实现TCP风格的数据可靠性保证,而不是UDP套接字tom-foolery,这是我的问题所在。
所以我现在已经在Java程序上工作了几个小时,我开始认为我不会找到答案。我正在eclipse中使用两个类,一个发送UDP数据报包,我已经通过socketsniff验证了绑定并发送到环回地址并具有正确格式化的有效负载。
第二类是我遇到问题的地方。在接收类中,我试图接收数据,但它永远不会到达那里。使用packetsniff,我发现在该套接字上甚至没有接收调用在运行代码时,它会在socket.receive()调用之前获得println语句,但它只是不运行它。有什么奇怪的,它会超时! 为什么不接收?
这是接收类的代码。
package us.wsu.compnet.reliabletransfer;
import java.io.*;
import java.net.*;
/**
* This class implements a receiver of the Stop-And-Wait reliable transfer protocol
*/
public class MyServerSocket implements Runnable {
private PipedOutputStream internalOutputStream; // Stream to which we write data for the upper layer
private PipedInputStream upperLayerStream; // Stream given to upper layer, connected to internalOutputStream
private DatagramSocket sock;
private DatagramPacket pack;
private byte[] buf;
private int seqNum;
/**
* Creates a receiver socket on a given port.
*/
public MyServerSocket(int port) throws SocketException {
// Open the UDP socket.
sock = new DatagramSocket(port);
System.out.println("" + sock.getInetAddress() + " " + sock.getPort() + "\n");
buf = new byte[1000];
pack = new DatagramPacket(buf,buf.length);
seqNum = 0;
// Create stream to the upper layer.
internalOutputStream = new PipedOutputStream();
try {upperLayerStream = new PipedInputStream(internalOutputStream);}
catch (IOException e) {/* This should not happen. */}
// Start thread that will receive the data packets and reply with acks.
(new Thread(this)).start();
}
/**
* Returns the InputStream associated with the socket.
*/
public InputStream getInputStream() {
return upperLayerStream;
}
/**
* Implementation of the receiver protocol.
*/
public void run() {
try{
// Receive datagram.
int x = 0;
sock.setSoTimeout(10000);
while (x < 10000)
{
try{
System.out.println("Waiting to recieve packet");
sock.receive(pack);
System.out.println("Packet Recieved");
}
catch(Exception e){
System.out.println("Swingandamiss!");
}
x++;
}
// Extract sequence number and data payload.
MyDataPacket p;
pack.setData(buf,0,pack.getLength()-1);
p = new MyDataPacket(buf,buf.length-1);
// If packet is received for the first time, deliver to upper layer.
if ( p.getSeqNum() == seqNum)
{
internalOutputStream.write(p.getData(), 0, p.getData().length);
seqNum = (byte) (1-seqNum);
}
// Send ack.
MyAckPacket ack;
ack = new MyAckPacket(seqNum);
DatagramPacket pout;
pout = new DatagramPacket(ack.toByteArray(),ack.toByteArray().length);
DatagramSocket outSock;
outSock = new DatagramSocket(pack.getPort(),pack.getAddress());
outSock.send(pout);
}
catch (IOException e){/*Do Nothing*/}
}
}
答案 0 :(得分:2)
你的代码错了。
您应该使用相同的DatagramSocket进行发送和接收。尝试使用源地址构造新代码的代码完全不正确,甚至不适用于非本地源代码。它也会泄漏插座。
您必须创建一个DatagramPacket,以便使用目标地址和端口进行发送。在响应的情况下,简单的方法是使用请求数据报并只更改其数据,使地址:端口保持不变。
您绝不能忽略异常。不要嘲笑他们不会发生,或者他们可以被忽视。他们会发生,他们不容忽视。在这种情况下,如果您没有如此忙于忽略它,那么在发送时会有一个例外(2),如果您没有那么忙,那么就会有例外。