<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Reliability and Flow Control</title>
	<atom:link href="http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/feed/" rel="self" type="application/rss+xml" />
	<link>http://gafferongames.com</link>
	<description>Glenn Fiedler&#039;s Game Development Articles and Tutorials</description>
	<lastBuildDate>Tue, 07 Sep 2010 17:03:11 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: Michael Nischt</title>
		<link>http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/#comment-963</link>
		<dc:creator>Michael Nischt</dc:creator>
		<pubDate>Thu, 29 Jul 2010 22:31:20 +0000</pubDate>
		<guid isPermaLink="false">http://gafferongames.wordpress.com/reliability-and-flow-control/#comment-963</guid>
		<description>actually it is as simply as:

static boolean isMoreRecentInSequence( int previous, int current )
{
return current - previous &gt; 0;
}

stupid me :-)</description>
		<content:encoded><![CDATA[<p>actually it is as simply as:</p>
<p>static boolean isMoreRecentInSequence( int previous, int current )<br />
{<br />
return current &#8211; previous &gt; 0;<br />
}</p>
<p>stupid me <img src='http://gafferongames.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Michael Nischt</title>
		<link>http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/#comment-962</link>
		<dc:creator>Michael Nischt</dc:creator>
		<pubDate>Fri, 23 Jul 2010 17:37:16 +0000</pubDate>
		<guid isPermaLink="false">http://gafferongames.wordpress.com/reliability-and-flow-control/#comment-962</guid>
		<description>great article!

btw. in case your language of choice doesn&#039;t support unsigned types (e.g. java/scala) or you simply try to avoid them (http://anteru.net/2010/05/17/736/):

    static boolean isMoreRecentInSequence( int previous, int current)
    {
        return ( current &gt; previous &amp;&amp; current-previous &gt;= 0 ) &#124;&#124;
               ( current &lt; previous &amp;&amp; previous-current &lt; 0 );
    }</description>
		<content:encoded><![CDATA[<p>great article!</p>
<p>btw. in case your language of choice doesn&#8217;t support unsigned types (e.g. java/scala) or you simply try to avoid them (<a href="http://anteru.net/2010/05/17/736/" rel="nofollow">http://anteru.net/2010/05/17/736/</a>):</p>
<p>    static boolean isMoreRecentInSequence( int previous, int current)<br />
    {<br />
        return ( current &gt; previous &amp;&amp; current-previous &gt;= 0 ) ||<br />
               ( current &lt; previous &amp;&amp; previous-current &lt; 0 );<br />
    }</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Glenn Fiedler</title>
		<link>http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/#comment-961</link>
		<dc:creator>Glenn Fiedler</dc:creator>
		<pubDate>Sat, 10 Jul 2010 18:14:57 +0000</pubDate>
		<guid isPermaLink="false">http://gafferongames.wordpress.com/reliability-and-flow-control/#comment-961</guid>
		<description>Here is a cool library to look in to for a general TCP replacement, with flow control, congestion avoidance and reliability

http://udt.sourceforge.net/

Also check out the papers on the site for a description of their congestion avoidance algorithm</description>
		<content:encoded><![CDATA[<p>Here is a cool library to look in to for a general TCP replacement, with flow control, congestion avoidance and reliability</p>
<p><a href="http://udt.sourceforge.net/" rel="nofollow">http://udt.sourceforge.net/</a></p>
<p>Also check out the papers on the site for a description of their congestion avoidance algorithm</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Glenn Fiedler</title>
		<link>http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/#comment-960</link>
		<dc:creator>Glenn Fiedler</dc:creator>
		<pubDate>Tue, 06 Jul 2010 21:04:35 +0000</pubDate>
		<guid isPermaLink="false">http://gafferongames.wordpress.com/reliability-and-flow-control/#comment-960</guid>
		<description>I should also note that in my own code (forked from this article, and unfortunately not publicly available) I have found and fixed a subtle bug related to the ack bitfield.

As presented in this article, the ack bitfield starts with ack - 1, but in reality the ack bitfield should start at ack. Otherwise, it&#039;s possible for the first few packets being sent out indicating acks where nothing was really acked at all, which can mess up reliable event queues driven by this system.

In other words, if you have a 16&#124;16&#124;32 header as described in this article, you can really only represent 32 acks per-packet, not 33.

cheers</description>
		<content:encoded><![CDATA[<p>I should also note that in my own code (forked from this article, and unfortunately not publicly available) I have found and fixed a subtle bug related to the ack bitfield.</p>
<p>As presented in this article, the ack bitfield starts with ack &#8211; 1, but in reality the ack bitfield should start at ack. Otherwise, it&#8217;s possible for the first few packets being sent out indicating acks where nothing was really acked at all, which can mess up reliable event queues driven by this system.</p>
<p>In other words, if you have a 16|16|32 header as described in this article, you can really only represent 32 acks per-packet, not 33.</p>
<p>cheers</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Glenn Fiedler</title>
		<link>http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/#comment-959</link>
		<dc:creator>Glenn Fiedler</dc:creator>
		<pubDate>Tue, 06 Jul 2010 20:48:27 +0000</pubDate>
		<guid isPermaLink="false">http://gafferongames.wordpress.com/reliability-and-flow-control/#comment-959</guid>
		<description>Sorry i meant two different things with a sliding window. You&#039;ll notice that the source code for this article uses a std::list for the acks, pending acks etc. This is incredibly inefficient. A much better data structure to use is a rolling fixed size queue, eg. a 256 size queue indexed by sequence number mod 256.

When I said that TCP uses a sliding window vs. what is done in this article, I meant only to highlight a few differences between what is presented in this article compared with TCP sequence numbers and acks.

This article assumes a constant bidirectional rate of packets being sent. This is why the sequence/ack/ackbits header works. It breaks down if you don&#039;t have a constant stream of packets.

Because of the constant flow assumption, this algorithm keeps sending packets even when the other side is not responding. The idea is that any lost data can be resent in a new packet (with a new sequence number). This is different from TCP, which will resend a specific packet with the same sequence number and gives much finer-grain control to the application over how it chooses to resend lost data (if at all).

The cost of this flexibility is that it is possible to &quot;lose&quot; acks. In other words for a packet to get through, but for the sender to not receive the corresponding ack! Making the ack bitfield wider lessens the chance of this occuring, and theoretically you could dynamically widen the ack bits in the header to make losing acks impossible, assuming some finite timeout value, but in general if you have about 2 seconds of redundant acks in my experience I&#039;ve found that is enough for average network conditions (so consider widening the ack bitfield in this article to 64, IMO)

In summary, the algorithm presented in this article is designed for constant flows and does not have any congestion avoidance or flow control built in. It&#039;s useful for situations when you can make assumptions about minimum bandwidth and maximum latency (eg. console games, PC broadband games). Also, you need to be aware that it&#039;s possible, although rare, for the sender to not receive an ack for packets that actually got through, resulting in redundantly resending data (and an additional bandwidth cost per-unit of data sent, in order to filter out duplicates events etc.)

cheers</description>
		<content:encoded><![CDATA[<p>Sorry i meant two different things with a sliding window. You&#8217;ll notice that the source code for this article uses a std::list for the acks, pending acks etc. This is incredibly inefficient. A much better data structure to use is a rolling fixed size queue, eg. a 256 size queue indexed by sequence number mod 256.</p>
<p>When I said that TCP uses a sliding window vs. what is done in this article, I meant only to highlight a few differences between what is presented in this article compared with TCP sequence numbers and acks.</p>
<p>This article assumes a constant bidirectional rate of packets being sent. This is why the sequence/ack/ackbits header works. It breaks down if you don&#8217;t have a constant stream of packets.</p>
<p>Because of the constant flow assumption, this algorithm keeps sending packets even when the other side is not responding. The idea is that any lost data can be resent in a new packet (with a new sequence number). This is different from TCP, which will resend a specific packet with the same sequence number and gives much finer-grain control to the application over how it chooses to resend lost data (if at all).</p>
<p>The cost of this flexibility is that it is possible to &#8220;lose&#8221; acks. In other words for a packet to get through, but for the sender to not receive the corresponding ack! Making the ack bitfield wider lessens the chance of this occuring, and theoretically you could dynamically widen the ack bits in the header to make losing acks impossible, assuming some finite timeout value, but in general if you have about 2 seconds of redundant acks in my experience I&#8217;ve found that is enough for average network conditions (so consider widening the ack bitfield in this article to 64, IMO)</p>
<p>In summary, the algorithm presented in this article is designed for constant flows and does not have any congestion avoidance or flow control built in. It&#8217;s useful for situations when you can make assumptions about minimum bandwidth and maximum latency (eg. console games, PC broadband games). Also, you need to be aware that it&#8217;s possible, although rare, for the sender to not receive an ack for packets that actually got through, resulting in redundantly resending data (and an additional bandwidth cost per-unit of data sent, in order to filter out duplicates events etc.)</p>
<p>cheers</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Kevin Smith</title>
		<link>http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/#comment-958</link>
		<dc:creator>Kevin Smith</dc:creator>
		<pubDate>Tue, 06 Jul 2010 15:46:27 +0000</pubDate>
		<guid isPermaLink="false">http://gafferongames.wordpress.com/reliability-and-flow-control/#comment-958</guid>
		<description>The article mentions TCP maintaining a sliding window and waiting for missing packets being the sort of behavior we want to avoid.  In a few comments you told that your code would be much more efficient if it was implemented using a proper fixed size sliding window.

Could you elaborate a little more on when it is good or bad to use a sliding window?</description>
		<content:encoded><![CDATA[<p>The article mentions TCP maintaining a sliding window and waiting for missing packets being the sort of behavior we want to avoid.  In a few comments you told that your code would be much more efficient if it was implemented using a proper fixed size sliding window.</p>
<p>Could you elaborate a little more on when it is good or bad to use a sliding window?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Glenn Fiedler</title>
		<link>http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/#comment-957</link>
		<dc:creator>Glenn Fiedler</dc:creator>
		<pubDate>Tue, 06 Jul 2010 14:58:39 +0000</pubDate>
		<guid isPermaLink="false">http://gafferongames.wordpress.com/reliability-and-flow-control/#comment-957</guid>
		<description>thanks and yes this article assumes a constant flow in both directions of 30pps. if you don&#039;t have a constant flow you&#039;ll need to do something more like what TCP does - cheers</description>
		<content:encoded><![CDATA[<p>thanks and yes this article assumes a constant flow in both directions of 30pps. if you don&#8217;t have a constant flow you&#8217;ll need to do something more like what TCP does &#8211; cheers</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Kevin Smith</title>
		<link>http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/#comment-956</link>
		<dc:creator>Kevin Smith</dc:creator>
		<pubDate>Mon, 05 Jul 2010 19:58:05 +0000</pubDate>
		<guid isPermaLink="false">http://gafferongames.wordpress.com/reliability-and-flow-control/#comment-956</guid>
		<description>At the bottom of my last comment I said &quot;replacement for timeouts&quot;, I meant &quot;replacement for keepalives&quot;</description>
		<content:encoded><![CDATA[<p>At the bottom of my last comment I said &#8220;replacement for timeouts&#8221;, I meant &#8220;replacement for keepalives&#8221;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Kevin Smith</title>
		<link>http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/#comment-955</link>
		<dc:creator>Kevin Smith</dc:creator>
		<pubDate>Mon, 05 Jul 2010 19:24:17 +0000</pubDate>
		<guid isPermaLink="false">http://gafferongames.wordpress.com/reliability-and-flow-control/#comment-955</guid>
		<description>First I would like to show my gratitude for all the time you spent on these articles and code for your readers! You are amazing dude :D

Under &quot;Reliable Acks&quot;  section you were talking about this:

&quot;So in our reliability system, we never resend a packet with a given sequence number. We sequence n exactly once, then we send n+1, n+2 and so on. We never stop and resend packet n if it was lost, we leave it up to the application to compose a new packet containing the data that was lost, if necessary, and this packet gets sent with a new sequence number.&quot;

Lets say a client sends chat message to sever.  Server sends out the chat message to everyone including the client.  For the client who sent the message, this reply packet should contain the ack.  But what happens if the server&#039;s packet was dropped?  The client would resend the message to the server after a timeout occured.  This message would have a new seq_num so the server would send out the chat message to everyone a second time.

I think what I got out of the article is that this algorithm assumes a constant packet flow back and forth.  Which means that even if the servers packet with the ack was dropped the next packet to be sent will likely arrive and it too will contain the ack.  However, there are times in all games where there is not much network traffic.  (Waiting in a lobby for the next game to start).  In these cases would you need to send a keepalive packet?
How would you determine when to send keepalive&#039;s?  You would need to send a keepalive before the timeout for the chat message. There is a possibility of the keepalive being dropped as well.  Which means that the chat message timeout might occur...

in &quot;Detecting Lost Packets&quot; section you seemed to hint at a work around for this:

&quot;The implication of this is that any data which you resend using this reliability technique needs to have its own message id so that if you receive it multiple times, you can discard it. This can be done at the application level.&quot;

Are the message id and packet seq_num two seperate fields?  i.e. [seq_num,ack,ack_bits,msg_id,chat_msg].  So you recieve the same message again but you can now check the msg_id against prev message ids and not send the chat message again?  Is this a replacement for timeouts or would both be needed?

Sorry this is so long winded but I have been thinking very hard how to implement my own code.</description>
		<content:encoded><![CDATA[<p>First I would like to show my gratitude for all the time you spent on these articles and code for your readers! You are amazing dude <img src='http://gafferongames.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Under &#8220;Reliable Acks&#8221;  section you were talking about this:</p>
<p>&#8220;So in our reliability system, we never resend a packet with a given sequence number. We sequence n exactly once, then we send n+1, n+2 and so on. We never stop and resend packet n if it was lost, we leave it up to the application to compose a new packet containing the data that was lost, if necessary, and this packet gets sent with a new sequence number.&#8221;</p>
<p>Lets say a client sends chat message to sever.  Server sends out the chat message to everyone including the client.  For the client who sent the message, this reply packet should contain the ack.  But what happens if the server&#8217;s packet was dropped?  The client would resend the message to the server after a timeout occured.  This message would have a new seq_num so the server would send out the chat message to everyone a second time.</p>
<p>I think what I got out of the article is that this algorithm assumes a constant packet flow back and forth.  Which means that even if the servers packet with the ack was dropped the next packet to be sent will likely arrive and it too will contain the ack.  However, there are times in all games where there is not much network traffic.  (Waiting in a lobby for the next game to start).  In these cases would you need to send a keepalive packet?<br />
How would you determine when to send keepalive&#8217;s?  You would need to send a keepalive before the timeout for the chat message. There is a possibility of the keepalive being dropped as well.  Which means that the chat message timeout might occur&#8230;</p>
<p>in &#8220;Detecting Lost Packets&#8221; section you seemed to hint at a work around for this:</p>
<p>&#8220;The implication of this is that any data which you resend using this reliability technique needs to have its own message id so that if you receive it multiple times, you can discard it. This can be done at the application level.&#8221;</p>
<p>Are the message id and packet seq_num two seperate fields?  i.e. [seq_num,ack,ack_bits,msg_id,chat_msg].  So you recieve the same message again but you can now check the msg_id against prev message ids and not send the chat message again?  Is this a replacement for timeouts or would both be needed?</p>
<p>Sorry this is so long winded but I have been thinking very hard how to implement my own code.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Dr.Kappa</title>
		<link>http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/#comment-954</link>
		<dc:creator>Dr.Kappa</dc:creator>
		<pubDate>Thu, 10 Jun 2010 09:05:03 +0000</pubDate>
		<guid isPermaLink="false">http://gafferongames.wordpress.com/reliability-and-flow-control/#comment-954</guid>
		<description>Bugs? Your articles+code are great! Thank you for sharing them!

I downloaded the other samples (Node mesh, Lan Matchmaking and Real world networking) and I&#039;m trying to figure out how to write a server/client resending lost packets...</description>
		<content:encoded><![CDATA[<p>Bugs? Your articles+code are great! Thank you for sharing them!</p>
<p>I downloaded the other samples (Node mesh, Lan Matchmaking and Real world networking) and I&#8217;m trying to figure out how to write a server/client resending lost packets&#8230;</p>
]]></content:encoded>
	</item>
</channel>
</rss>
