Jump to content
  • Advertisement
Sign in to follow this  
md_lasalle

Handling UDP resends

This topic is 3500 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey all, I've written a small network lib using the UDP protocol. Right now, I have set the resend interval to 500ms, meaning if I don't receive an ACK from the other side, I resend the packet, then wait another 500ms before re-resending the packet. The problem I see with that approach is that I'm forcing a 500ms lag to my players if 1 packet is lost. My first Idea was to determine the resend delay per clients according to his ping, but ping measurement is never really accurate and has lots of variations. On the other end, I don't want my server to start resending packets like crazy thus eating all my upload bandwidth. What approach would you guys recommend ? The game is very fast paced/projectile intensive, is in a client/server architecture and up to 16 players max can be connected to the server at the same time.

Share this post


Link to post
Share on other sites
Advertisement
This is the method which many UDP based games that want reliable delivery use, the author also has other articles which may interest you.

Share this post


Link to post
Share on other sites
Very good article. Some of his concept don't apply for me because of my implementation, but I guess that measuring the average RTT of ACK packets would be a good start.

Share this post


Link to post
Share on other sites
Quote:
Original post by md_lasalle
Very good article. Some of his concept don't apply for me because of my implementation, but I guess that measuring the average RTT of ACK packets would be a good start.


The most important concept you need to implement is asynchronous and unreliable sending. You cannot wait for ack of every message. You keep sending regardless of acks, but maintain in-transit buffer to not flood the peer. This is the most important part, since your individual simulations can progress even if one or several stall for any reason.

There is alternate approach which can, sometimes, be used to minimize the resends. Sequential packets can be encoded using Reed Solomon (possibly in combination with convolution) encoding. There, information from several packets is merged. This adds some overhead to each individual packet, but original data can be reconstructed even when some packets never arrive.

Whether such approach is practical or not has to be determined on per-case basis.

Share this post


Link to post
Share on other sites
The terms to google for include "windowing" and "RTT estimation." Both of which are implemented in TCP, by the way -- if you need sequential, in-order delivery, you might as well use TCP.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
The most important concept you need to implement is asynchronous and unreliable sending. You cannot wait for ack of every message. You keep sending regardless of acks, but maintain in-transit buffer to not flood the peer. This is the most important part, since your individual simulations can progress even if one or several stall for any reason.


Yes, this is what I did it : 1 physical UDP packet can contain multiple :
- safe user packets
- unsafe user packets
- safe user packet resends

When I say "user packet" I mean game layer packet, meaning the network lib is not game specific.


Quote:
Original post by hplus0603
The terms to google for include "windowing" and "RTT estimation." Both of which are implemented in TCP, by the way -- if you need sequential, in-order delivery, you might as well use TCP.


I have experienced with TCP before, my first game which is widely played at the moment is entirely TCP, and what I have noticed, compared to the new version that will use UDP, is that TCP can take forever before it detects/resends a lost packet, which happens quite often over wireless networks and with client on poor ISP connections.

With current implementation, I'm taking advantage of UDP by letting the Game App level tag user packets as Safe/Unsafe depending on the need.

Thanks for the inputs so far.



Share this post


Link to post
Share on other sites
Quote:
Yes, this is what I did it : 1 physical UDP packet can contain multiple :


His suggestion was that you window the amount of physical UDP packets you can have outstanding on the wire at the same time. Put a sequence number in each physical packet. When you send packets back, send acks for the last N sequence numbers you've received. When the sending end has sent N packets without receiving an ack for the first packet, start re-sending from that packet. As long as (packet send rate * N) is larger than (round trip time) this will be perfectly stable.

The size of "N" is your window size, and it sounds like your current implementation has N == 1, which is usually not the optimal window size.

Share this post


Link to post
Share on other sites
Currently, I don't resend physical packets, since they can contain both safe/unsafe data. If a safe user packet needs to be resent, it will get merged in the next physical packet to send, in-front of the new data to be sent, until my maximum send size is reached (which is about 1200 bytes per packet on the xbox, and imposing the same limit on PC seems to be good enough for me, my packets rarely go over 600 bytes)

It might not be the best approach, but it is definitely running smooth with 16 players and intense action, especially since I'm not sending at the same rate for every client on the map, so the upload on the server is distributed over multiple game logic frames.

Going from there I'm still opened to recommendations that fits my current design.

Share this post


Link to post
Share on other sites
Quote:
Original post by md_lasalle
... (which is about 1200 bytes per packet on the xbox, and imposing the same limit on PC seems to be good enough for me, my packets rarely go over 600 bytes)


By this are you implying that your packets are not a uniform size? I listened to a lecture from Ben Garney from GDC in which he says that you should favour packets of uniform size as routers tend to favour data like this than packets of varying sizes.

If you say your packets are 600bytes and you have 16 players with an update every 20th of a second then you have a 8.78kbs upstream usage, which is too much for the xbox360 as the limit is 8kbs.

Share this post


Link to post
Share on other sites
What is your unit of re-send? Are you saying that if a user-level message has not been delivered in 500ms, that user-level message gets re-queued for physical packet inclusion?

In general, you want to track your physical packets with sequence numbers, and then "know" which user-level messages have "made it" or not by tracking which physical packets have made it across. In general, you also want to allow multiple physical packets to be outstanding before you get an ack from the other end. Once you have those two pieces implemented, doing "optimal" re-send of reliable messages into physical packets based on latency is mostly an exercise in accounting and adding/removing things onto keyed lists.

Perhaps this is what you're already doing, in which case you're doing fine. But then the original question makes no sense to me?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!