[英]Java Udp sockets, packets lost in localhost
I am implementing a simple java udp socket program. 我正在实现一个简单的Java udp套接字程序。 Here are the details:
详细信息如下:
Here is the problem: The for loop in client side never ends! 这是问题所在:客户端中的for循环永远不会结束! that means 2500 packets are never received!
这意味着将永远不会收到2500个数据包! Although I checked server side and it has sent them all.
虽然我检查了服务器端,并已将它们全部发送出去。
I tried setting the socket's receive buffer size to 10 * packetSize
using this: 我尝试使用以下方法将套接字的接收缓冲区大小设置为
10 * packetSize
:
socket.setReceiveBufferSize(10 * packetSize)
but it does not work. 但它不起作用。
How do you think I could solve this problem? 您认为我如何解决这个问题? I know UDP is not reliable but both client and server are running on different ports of the same computer!
我知道UDP不可靠,但是客户端和服务器都在同一台计算机的不同端口上运行!
Here is the code for server side: 这是服务器端的代码:
for (int i = 0; i < packets; i++) {
byte[] currentPacket = new byte[size];
byte[] seqnum = intToByteArray(i);
currentPacket[0] = seqnum[0];
currentPacket[1] = seqnum[1];
currentPacket[2] = seqnum[2];
currentPacket[3] = seqnum[3];
for (int j = 0; j < size-4; j++) {
currentPacket[j+4] = finFile[i][j];
}
sendPacket = new DatagramPacket(currentPacket, currentPacket.length, receiverIP, receiverPort);
socket.send(sendPacket);
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
and the client side: 和客户端:
int k = 0;
while (true) {
receivedBytes = new byte[size];
receivePacket = new DatagramPacket(receivedBytes, size);
socket.receive(receivePacket);
allBytes.add(receivePacket.getData());
k++;
if (k == packets)
break;
}
allBytes
is just a linked list containing received bytes. allBytes
只是一个包含已接收字节的链表。 i use it to reassemble the final file. 我用它来重组最终文件。
PS This code works perfect for under 100Mb files. PS此代码非常适合100Mb以下的文件。 Thanks
谢谢
Update: tl;dr summary: Either packets
is not properly initialized or use TCP, or add a sequence number in your UDP packet so that your client knows if it drops a packet and you can write code to handle that (request for a rebroadcast). 更新:tl; dr摘要:
packets
未正确初始化或未使用TCP,或在UDP数据包中添加了序列号,以便您的客户端知道它是否丢弃了数据包,并且您可以编写代码来处理该数据包(请求重播) 。 This essentially makes it a rudimentary TCP anyways. 无论如何,这本质上使其成为基本的TCP。
I have a suspicion that you never initialized packets
so you never hit your break
. 我怀疑您从未初始化
packets
因此您从未break
。 Rewriting your while
into a for
loop can easily check if this is true. 将您的
while
重写为for
循环可以轻松检查是否为真。 Assuming the first packet you send contains how many packets it will be receiving, and you initialize packets
correctly then if your packets are being lost then your client side program will not end since receive() is a blocking method. 假设您发送的第一个数据包包含将要接收的数据包,并且您正确地初始化了
packets
,那么如果您的数据包丢失了,您的客户端程序将不会结束,因为receive()是一种阻塞方法。
If you strongly suspect that your packets are being lost, then debug your client side and see how many received packets are in your LinkedList and compare that against how many are sent on the server side. 如果您强烈怀疑丢失了数据包,请调试客户端,查看LinkedList中有多少个接收到的数据包,并将其与服务器端发送的数据包进行比较。
for(int i = 0; i < packets; i++) {
receivedBytes = new byte[size];
receivePacket = new DatagramPacket(receivedBytes, size);
socket.receive(receivePacket);
allBytes.add(receivePacket.getData());
}
System.out.println("All " + packet + " received.");
Switching to code to the above will let you know that if you never get to the print statement, then you know that you're losing packets since receive() is a blocking method and it means that your client side is stuck in the for
loop. 切换到上面的代码将使您知道,如果您从未使用过print语句,那么您就会知道丢失数据包,因为receive()是一种阻塞方法,这意味着您的客户端陷入了
for
循环中。 This is because the for
loop can't be satisfied since if the server sends 2500 packets but the client only receives 2300 packets, it'll still be in the for loop at the receive() line waiting for 2301, 2302, ... packets and so on. 这是因为无法满足
for
循环的需要,因为如果服务器发送了2500个数据包,但客户端仅接收了2300个数据包,则它仍将在receive()行的for循环中等待2301、2302,...数据包等。
Since you have a file with upwards of 100MB or more that needs to be assembled I assume you can't tolerate loss, so either use TCP that will fulfill that requirement or handle that possibility in your code by creating your own header with each packet. 由于您需要组装的文件大于或等于100MB,我假设您无法承受丢失,因此请使用可以满足该要求的TCP,或者通过在每个数据包中创建自己的标头来处理这种可能性。 This header can be as simple as an incrementing sequence number that the client will receive and read, if it skips a number from the previous packet then it will know that a packet was lost.
该报头可以像客户端将要接收和读取的递增序号一样简单,如果它跳过前一个数据包中的数字,则它将知道一个数据包丢失了。 At this point, you can have your client request the server to rebroadcast that specific packet.
此时,您可以让客户端请求服务器重新广播该特定数据包。 But at this point you just implemented your own crude TCP.
但是,此时您仅实现了自己的原始TCP。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.