【发布时间】:2015-04-10 20:01:06
【问题描述】:
我正在开发一个项目,该项目假设使用 DatagramPackets 和 DatagramSockets 将文件从一台机器发送到另一台机器。该实现被假设为模仿 TCP 协议。因此,一旦接收方收到一个数据包,它就会向发送方发回一个 ACK,确认数据包已送达。到目前为止,我的程序没有对 ACK 进行任何检查。我无法实现 ACK 消息。在我的接收程序上,它显示正在发送 ACK,但发送方应用程序没有收到它们。
我在创建套接字时不断收到错误消息。 “java.net.BindException:地址已在使用中:无法绑定”。我很困惑,因为发件人应用程序中的其他任何地方都没有指定端口。我只是使用DatagramSocket socket = new DatagramSocket();
但我确实使用
DatagramPacket packet = new DatagramPacket(packetData, packetData.length, internetAddress, 49000);
socket.send(packet); 发送数据包时。
我尝试在我的 waitForAck() 方法中删除数据报声明,并使用与发送数据包相同的 datagramSocket。但是socket.receive(packet); 会挂起并且永远不会收到任何东西,因为它没有被分配一个端口来监听。
这是我监听 ACK 的方法:
public void waitForACK(){
//listen for ack for a period of time
//if ACK received, then break send next packet
//if ACK not received or time out, send last packet
//TODO: implement a timeout
System.out.println("### Sender waiting for ACK");
try {
DatagramSocket receivingSocket = new DatagramSocket(49000);
while (!ACKreceived) {
byte[] buf = new byte[1500]; // Actual Ethernet packet size is 1500 bytes
// receive request
DatagramPacket packet = new DatagramPacket(buf, buf.length);
receivingSocket.receive(packet); //socket.receive(packet); <--
byte[] packetData = Arrays.copyOf(packet.getData(), packet.getLength());
ACKreceived = checkACK(packetData);//check the recieved packet contains an ACK message
}
System.out.println("### Sender recieved ACK");
} catch (Exception e) {
System.out.println("### never got ACK");
System.out.println(e);
}
}
我也尝试过这个,但是 scoket 会挂起,实际上从来没有收到任何东西。即使接收文件的应用程序成功报告发送 ACK。我猜是因为它不知道在端口 49000 上接收 ACK。
public void waitForACK(){
//listen for ack for a period of time
//if ACK received, then break send next packet
//if ACK not received or time out, send last packet
//TODO: implement a timeout
System.out.println("### Sender waiting for ACK");
try {
while (!ACKreceived) {
byte[] buf = new byte[1500]; // Actual Ethernet packet size is 1500 bytes
// receive request
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet); //<--- HANGS RIGHT HERE
byte[] packetData = Arrays.copyOf(packet.getData(), packet.getLength());
ACKreceived = checkACK(packetData);//check the recieved packet contains an ACK message
}
System.out.println("### Sender recieved ACK");
} catch (Exception e) {
System.out.println("### never got ACK");
System.out.println(e);
}
}
【问题讨论】:
-
在端口空闲时使用 netstat 等工具进行绑定错误检查。 “已在使用”意味着肯定即使您的代码未绑定某些进程。您编辑的代码看起来如何? (你说你在哪里删除了
Datagram声明? -
我编辑了我的帖子以包含您要求的代码。这只是我的 waitForACK() 方法的修改版本。与此同时,我将对 netstat 进行一些研究。
-
对方是否明确发送到49000端口?本地端口和对等端口通常不相同,除非您明确将它们设为相同,因此您发送到 49000 的事实并不意味着您应该期望在 49000 上接收。
标签: java sockets tcp udp datagram