TCP uses a 24 byte header:
0 16 31
| Source Port | Destination port |
+---------------------------------+
| Sequence Number |
+---------------------------------+
| Acknowledgement number |
+--+-----+++++++------------------+
|HL| Res ||||||| Windows | HL - Header Length, Res - Reserved
+--+-----+++++++------------------+
| Checksum | Urgent Pointer |
+--------------+------------+-----+
| Options( if any ) | Pad | Pad - padding
+---------------------------+-----+
| Data |
.
.
.
(Extracted from Unix Unleashed, System Adminitrator's edition)
The blanks between Reserved and Window is a series of flags.
I think your probably falling victim to the Checksum and perhaps a low
urgency. If your gonna do any TCP/IP work, you better get some good
books so you'll know how to tweak it. My book only goes into the
structure layout. Not really too much into the details( it refers the
reader to other books more in-depth ).
Robert
I'm involved with a project writing a combination
shoot-em-up/strategy game for Windows 95, and I'm currently attempting
to get multiplayer network play running.
I have experimented with both UDP and TCP communication, using a
client/server architecture, and found the UDP was *much* faster than
TCP, even with the client and server on the same machine. However, UDP
appears to be annoyingly difficult to get to work reliably, and I
would really like to use TCP if possible. I have been told that
transmission times with TCP should be very close to UDPs with Nagel's
algorithm disabled, but I found this had little effect on the speed!
Unfortunately, due to the nature of the game, the clients are all
frame-locked (hence there is little advantage in UDP's lack of
resends, as the packet has to be resent the the game anyway!),
although the advantage of this is that only ~16 bytes have to be sent
per frame.
Does anyone have any suggestions on why TCP is apparently so slow, or
should I simply be using UDP! (or, failing that, DPlay <shudder>)
Thanks!
--
Ben Carter - b...@gunk.demon.co.uk - http://www.gunk.demon.co.uk/
-----------------------------------------------------------------
"Shut up! How're we supposed to be the bad guys if we go about
worrying about our *lives* all the time?" - Grandis Granbar, "The
Secret of Blue Water"
-----------------------------------------------------------------
Robert J. Sprawls escribió en mensaje
<6mn45c$8...@bgtnsc01.worldnet.att.net>...
>Ben Carter wrote:
>>
>> I'm involved with a project writing a combination
>> shoot-em-up/strategy game for Windows 95, and I'm currently attempting
>> to get multiplayer network play running.
>>
>> I have experimented with both UDP and TCP communication, using a
>> client/server architecture, and found the UDP was *much* faster than
>> TCP, even with the client and server on the same machine. However, UDP
>> appears to be annoyingly difficult to get to work reliably, and I
>> would really like to use TCP if possible. I have been told that
>> transmission times with TCP should be very close to UDPs with Nagel's
>> algorithm disabled, but I found this had little effect on the speed!
>>
>> Unfortunately, due to the nature of the game, the clients are all
>> frame-locked (hence there is little advantage in UDP's lack of
>> resends, as the packet has to be resent the the game anyway!),
>> although the advantage of this is that only ~16 bytes have to be sent
>> per frame.
>>
>> Does anyone have any suggestions on why TCP is apparently so slow, or
>> should I simply be using UDP! (or, failing that, DPlay <shudder>)
>>
I strongly recommend you keeping with UDP. If you have to send reliable
packets make the packet have a reliable flag and client sending an ACK for
those reliable packets.
TCP/IP has more problems than the overhead it adds. I strongly recommend UDP
for any arcade type of game...
David Notario
Ben Carter wrote in message <358ef1e3...@news.demon.co.uk>...
> I have experimented with both UDP and TCP communication, using a
>client/server architecture, and found the UDP was *much* faster than
>TCP, even with the client and server on the same machine. However, UDP
>appears to be annoyingly difficult to get to work reliably, and I
>would really like to use TCP if possible. I have been told that
>transmission times with TCP should be very close to UDPs with Nagel's
>algorithm disabled, but I found this had little effect on the speed!
TCP is a *guaranteed* connection - no packet loss and no corruption. To do
this, there is a lot of control overhead going on behind the scenes. This
control overhead takes time.
UDP has none of this overhead, but then again you are not guaranteed
anything.
> Does anyone have any suggestions on why TCP is apparently so slow, or
>should I simply be using UDP! (or, failing that, DPlay <shudder>)
Use TCP. It'll save you the hassle of having to program your own rerequest
and consensus and God knows what other horrid algorithms you need to
guarantee your packets get through.
Ozzy
Paul 'Ozymandias' Harman wrote:
>TCP is a *guaranteed* connection - no packet loss and no corruption. To do
>this, there is a lot of control overhead going on behind the scenes. This
>control overhead takes time.
Yep, but there's *too much* overhead for a decent game, IMHO. No corruption
is guaranteed by the underlying IP anyway, and you can come up with a much
simpler scheme to prevent packet loss than the one TCP has..
>> Does anyone have any suggestions on why TCP is apparently so slow, or
>>should I simply be using UDP! (or, failing that, DPlay <shudder>)
>
>Use TCP. It'll save you the hassle of having to program your own rerequest
>and consensus and God knows what other horrid algorithms you need to
>guarantee your packets get through.
Well, yes. But be aware that the loss of a packet can lead to resynching
times in the range of 2-5 minutes, basically blocking your process in the
meantime. (Unless you use non-blocking I/O, but even then it would be simply
too long for a game).
If you're only targetting W95 as a platform and are not into massive
multiplayer, I suggest going with DPlay. You get modem play for free
(basically :-), and even if your computer has no TCP stack installed, you
can still fallback to IPX.
Bye,
Robert
Robert Blum wrote in message <6mntle$b0j$1...@news.seicom.net>...
>Paul 'Ozymandias' Harman wrote:
>>TCP is a *guaranteed* connection - no packet loss and no corruption. To do
>>this, there is a lot of control overhead going on behind the scenes. This
>>control overhead takes time.
>Yep, but there's *too much* overhead for a decent game, IMHO. No corruption
>is guaranteed by the underlying IP anyway, and you can come up with a much
>simpler scheme to prevent packet loss than the one TCP has..
Does the IP bit of TCP/IP guarantee packets? I didn't realise (remember)
that. A simple Positive Acknowledge scheme would work, but why bother
writing it if it's in TCP?
[You provide the answer in the resynching overhead below]
>>Use TCP. It'll save you the hassle of having to program your own rerequest
>>and consensus and God knows what other horrid algorithms you need to
>>guarantee your packets get through.
>Well, yes. But be aware that the loss of a packet can lead to resynching
>times in the range of 2-5 minutes, basically blocking your process in the
>meantime. (Unless you use non-blocking I/O, but even then it would be
simply
>too long for a game).
If the resynching proves a problem, don't use it. Write your own, I'd
suggest a positive acknowledge scheme: if a packet arrivbes and it is not
corrupt (use a simple CRC on the packet) then send an "it's okay" message
back. If the packet didn't arrive, or it arrived corrupt, do nothing. If the
sender doesn't receive an ACK within a certain time period, resend the
packet.
>If you're only targetting W95 as a platform and are not into massive
>multiplayer, I suggest going with DPlay. You get modem play for free
>(basically :-), and even if your computer has no TCP stack installed, you
>can still fallback to IPX.
True. DPlay is 'good' because it hides the underlying protocol from you.
(Although there are lots of undocumented features at least in DX3...)
If you're playing across the Internet though... either use UDP/IP or TCP/IP,
or look into the DirectPlay Lobby standard (about which I know nothing).
Ozzy
Paul 'Ozymandias' Harman wrote
>Does the IP bit of TCP/IP guarantee packets? I didn't realise (remember)
>that. A simple Positive Acknowledge scheme would work, but why bother
>writing it if it's in TCP?
No, IP does only guarantee your packets are not corrupted. (Well,
guarantee... It computes a simple checksum)
>If the resynching proves a problem, don't use it. Write your own, I'd
>suggest a positive acknowledge scheme: if a packet arrivbes and it is not
>corrupt (use a simple CRC on the packet) then send an "it's okay" message
>back. If the packet didn't arrive, or it arrived corrupt, do nothing. If
the
>sender doesn't receive an ACK within a certain time period, resend the
>packet.
That's almost the same algorithm I used. However, if you can afford losing a
packet or two, modify this scheme to give your packets sequence numbers.
E.g: Server sends up to n unacknowledged packets. If there's no acknowledge
either in a certain timeframe or after sending n packets, the server only
resends the last packet.
Client acknowledges every packet gotten, using the sequence number. Out of
sequence packets are dropped, as well as corrupt ones. You can even choose
to acknowledge only every 2nd, 3rd or whatever packet unless you get an out
of sequence or a corrupt packet.
If your game transmits only absolute, not relative data, you _can_ get away
with this.
Bye,
Robert
Robert Blum wrote in message <6mo1ob$gfj$1...@news.seicom.net>...
>No, IP does only guarantee your packets are not corrupted. (Well,
>guarantee... It computes a simple checksum)
Ah... so you can get packets out of order with IP, or no packet at all, but
anythign you *do* get is not corrupted.
[snip Positive Acknowledge system]
>That's almost the same algorithm I used. However, if you can afford losing
a
>packet or two, modify this scheme to give your packets sequence numbers.
[snip 'window' extension to positive ack system]
I've done a fair bit of networking theory (just forgot what TCP/IP used),
and yes you can implement clever schemes based on sequence numbers and
reordering pckets etc etc... but is it really worth it in a game context?
Not wanting to do your method down by any means (honest) };*), in fact it
has merits in that the server doesn't have to wait for acks all the time and
so it can spend more time running the actual game. It depends on how
paranoid you are with the network, and frankly I'd rather let the
"networking infrastructure" do it for me than have to worry about it myself.
If that means usign TCP/IP, IPX, DirectPlay, WinSock, or whatever, then so
be it. YMMV.
>If your game transmits only absolute, not relative data, you _can_ get away
>with this.
Yes, but...
If you are guaranteed packet ordering, always transmit "delta" (i.e.
changes) information rather than "absolute" information because the delta
information is invariably smaller. However, where you are not guaranteed
anything of the sort, absolutes become necessary although you can probably
get away with sending !absolutes that have changed in the last 10 game
cycles) or somesuch.
Ozzy
>
<snip>
>Robert Blum wrote in message <6mntle$b0j$1...@news.seicom.net>...
>Does the IP bit of TCP/IP guarantee packets? I didn't realise (remember)
>that. A simple Positive Acknowledge scheme would work, but why bother
>writing it if it's in TCP?
No, IP does not guarantee packets. That's what TCP does for you - so
you're right, there's no reason to write it.
>[You provide the answer in the resynching overhead below]
>
>>>Use TCP. It'll save you the hassle of having to program your own rerequest
>>>and consensus and God knows what other horrid algorithms you need to
>>>guarantee your packets get through.
>>Well, yes. But be aware that the loss of a packet can lead to resynching
>>times in the range of 2-5 minutes, basically blocking your process in the
>>meantime. (Unless you use non-blocking I/O, but even then it would be
>simply
>>too long for a game).
>
>If the resynching proves a problem, don't use it. Write your own, I'd
>suggest a positive acknowledge scheme: if a packet arrivbes and it is not
>corrupt (use a simple CRC on the packet) then send an "it's okay" message
>back. If the packet didn't arrive, or it arrived corrupt, do nothing. If the
>sender doesn't receive an ACK within a certain time period, resend the
>packet.
I don't believe you can *not* use the resynching aspect of TCP - it's
part of the protocol. In order to avoid that and write your own,
you'd start with UDP and write it in. However, I agree with Robert -
you'd be killing your performance to write that on top of UDP (for
anything but a turn-based game, at any rate). Besides, providing for
positive ACKs would mandate some kind of windowed transfer scheme,
etc., and that would get pretty wooly. No reason to rewrite TCP from
UDP...
______________________________________________________________
Brian Hall
bh...@cyberhighway.net
"Just once in my life I'd like the chance to shoot an educated man."
Absolutely. Your 'positive acknowedgement' system results
in a lock step, only advancing every 2*latency ms. That means
you'll get (approximately) 2 ack'd packets per second.
(Assuming ~250ms pings). This is, obviously, useless for
any sort of action game.
>Not wanting to do your method down by any means
>(honest) };*), in fact it has merits in that the server doesn't
>have to wait for acks all the time and so it can spend more
>time running the actual game. It depends on how
>paranoid you are with the network, and frankly I'd rather
>let the "networking infrastructure" do it for me than have
>to worry about it myself. If that means usign TCP/IP, IPX,
>DirectPlay, WinSock, or whatever, then so be it. YMMV.
WinSock is an API and IPX has the same properties as
UDP. TCP/IP is useless on anything but a perfect network
connection. With that 250ms latency, a forced resend will
take over 750ms from start to finish. (The 'over' is because
you don't know you need a resend until either the next
packet arrives, or a timeout occurs). If you use TCP, you
can kiss goodbye to playability on anything less than a T1.
>>If your game transmits only absolute, not relative data, you
>>_can_ get away with this.
>
>Yes, but...
>
>If you are guaranteed packet ordering, always transmit
>"delta" (i.e. changes) information rather than "absolute"
>information because the delta information is invariably
>smaller.
Unfortunately, you *can't* guarantee ordering without
a major performance hit. Your deltas are useless if you
need to wait a second to find where you should have
been 1/20th of a second later. Bandwidth is usually
much less of a problem than latency.
>However, where you are not guaranteed anything of the
>sort, absolutes become necessary although you can
>probably get away with sending !absolutes that have
>changed in the last 10 game cycles) or somesuch.
Yup. Deltas are fine if you send multiple updates in the
packet (e.g.: the last 3 ticks). That way, you can drop
up to 2 consecutive packets and still be able to build
a continuous stream. If the connection is worse than
that, you can't be expected to make much of it (although,
a simple feedback system could be used to 'repair'
bad connections at the cost of bandwidth by sending
more updates per packet).
---
Russ
Agreed absolutely. I tried this scheme myself in my Degree project. It was
far, far too slow. I was trying to outline something simple. Apologies for
not explaining this before, but I didn't want to go into a 1000-line essay
on the relative merits of networking protocols.
>WinSock is an API and IPX has the same properties as
>UDP. TCP/IP is useless on anything but a perfect network
>connection. With that 250ms latency, a forced resend will
>take over 750ms from start to finish. (The 'over' is because
>you don't know you need a resend until either the next
>packet arrives, or a timeout occurs). If you use TCP, you
>can kiss goodbye to playability on anything less than a T1.
I'm mixing and matching layers of abstraction, aren't I! (If TCP/IP is
useless on anything bar a perfect network, then why have it, since it's
primary advantage is error detection and correction?)
I agree (now) that TCP/IP is too slow for games.
>Unfortunately, you *can't* guarantee ordering without
>a major performance hit. Your deltas are useless if you
>need to wait a second to find where you should have
>been 1/20th of a second later. Bandwidth is usually
>much less of a problem than latency.
That depends on how much is 'changing' in the game and how many machines are
playing, but I agree in principle. I backed down mid-post last time and said
that using a 'window' method has benefits because you are no longer
dependent on lock-steps.
One possible alternative is to send deltas every nth of a second and full
updates every second. (Choose a longer time frame as applicable).
>Yup. Deltas are fine if you send multiple updates in the
>packet (e.g.: the last 3 ticks). That way, you can drop
>up to 2 consecutive packets and still be able to build
>a continuous stream. If the connection is worse than
>that, you can't be expected to make much of it (although,
>a simple feedback system could be used to 'repair'
>bad connections at the cost of bandwidth by sending
>more updates per packet).
What an intriguing couple of suggestions....
Ozzy
It's mostly for FTP and WWW type applications. You
want downloaded file packets to appear, in order,
without errors. It removes most of the hassle from
getting data from A to B. Latency isn't an issue,
usually, and the impact on bandwidth is fairly small.
>I agree (now) that TCP/IP is too slow for games.
Yup. Quake is somewhat misleading by calling it
TCP/IP when it uses UDP/IP. QTest used TCP and,
by Carmacks admission, was unplayable. He
apparently spent almost all the time from QTest to
Quake rewrtiting the code to use UDP and expect
packet loss.
>>Unfortunately, you *can't* guarantee ordering without
>>a major performance hit. Your deltas are useless if you
>>need to wait a second to find where you should have
>>been 1/20th of a second later. Bandwidth is usually
>>much less of a problem than latency.
>
>That depends on how much is 'changing' in the game and
>how many machines are playing, but I agree in principle.
Yup.
>I backed down mid-post last time and said that using a
>'window' method has benefits because you are no longer
>dependent on lock-steps.
>
>One possible alternative is to send deltas every nth of a
>second and full updates every second. (Choose a longer
>time frame as applicable).
I believe I suggested that to Javier Aravelo a couple of
weeks ago. It's a good idea to send absolutes
occasionally - it prevents errors mounting up and
makes for easy non-linear display of recordings:
(playing backwards, seeking to any point, user editing
to add text, etc.)
>>Yup. Deltas are fine if you send multiple updates in the
>>packet (e.g.: the last 3 ticks). That way, you can drop
>>up to 2 consecutive packets and still be able to build
>>a continuous stream. If the connection is worse than
>>that, you can't be expected to make much of it (although,
>>a simple feedback system could be used to 'repair'
>>bad connections at the cost of bandwidth by sending
>>more updates per packet).
>
>What an intriguing couple of suggestions....
There are big advantages to doing your own error
correction :)
I'm not sure if Quake uses this. I know that the sent
packets can contain multiple 'game packets', but I
don't know if there's redundancy in there.
---
Russ
Yes... The system I tried with UDP was to use timeouts, rather than
any ACK packets, but it was still too slow... I think that "real" net
play (as opposed to TCP/IP over a LAN) is going to be downright
impossible whatever happens, simply as the game is not designed to
handle *any* latency or client prediction (basically, every client
*must* have the same information each frame, otherwise they will slip
out of sync!).
I think I'll go any try and code it with DPlay, and see what happens
then... (assuming I can understand the API at all...)
Thanks for all the suggestions!
Ben Carter wrote in message <358ef1e3...@news.demon.co.uk>...
: I have experimented with both UDP and TCP communication, using a
:client/server architecture, and found the UDP was *much* faster than
:TCP, even with the client and server on the same machine. However, UDP
:appears to be annoyingly difficult to get to work reliably, and I
:would really like to use TCP if possible. I have been told that
:transmission times with TCP should be very close to UDPs with Nagel's
:algorithm disabled, but I found this had little effect on the speed!
I've found on mega-multiplayer games you probably need Nagle's with TCP on
the server end to make communications efficient. As you notice the time
delay difference is really small (at worst ~200ms.)
I spent several months working with UDP and found I had to drop it because
many IP peers will not route UDP packets under any circumstance. Also when
the net gets very clogged the backbone servers start dropping UDP. TCP can
get really backed up but it always comes through. Ask yourself whether your
game can tolerate 100% packet loss during peak hours.
Another annoying problem I had with UDP was out of order packets. I could
handle it if the duck jumped forward two spaces because of packet loss. But
when the duck jumped forward two, back one, then forward three -- things got
wierd. It was much harder for me to program for out of order than simple
packet loss. Your mileage may vary, of course.
Actually, what was meant in the previous post was that IP does do integrity
checking of the packet using a checksum, so the chance of a corrupt packet
arriving is quite low. Ethernet has its own crc'ing etc.
TCP isn't useful for realtime data, especially not since for realtime data
it's better to get a later packet through than to get the previous, blocked,
packets through. I.e., your game can handle packet loss so there is no need
to resend and ack a packet - if you need to resend it, you might as well
send a more up-to-date packet! So, UDP is much better if you don't need 100%
certain delivery.
Even for protocols requiring resending, writing your own mechanism using UDP
will be better than TCP, we've done this with a MUD multiplexer protocol,
enabling MUD muxes be positioned locally in a country, muxing several TCP
connections and compressing them into our own UDP protocol to the actual MUD
server. The UDP protocol over the atlantic for example provides a _much_
better realtime response than a TCP link would, because our parameters are
better tuned for modern TCP/IP long-distance networks. But writing this
requires of course a firm knowledge of TCP, if you don't want to spend a lot
of time learning TCP/IP (which is very useful!) and still need 100%
delivery, use TCP (or DPlay? Dunno if that supports guaranteed delivery).
/Bjorn
Now, back to TCP. TCP has all sorts of very complicated code, where it times
the incoming ACKs to space it's outgoing data, so in theory it self adjusts
to the quality of the link. TCP is far better suited for reliable
connections in most cases. You aren't going to be able to do much better
than TCP in most cases (non games applications). But, TCP assumes that the
connection isn't hugely congested. Once you start introducing a 28.8 modem,
and 30 packets per second, each 100 bytes, TCP just falls apart. In our
case, most of the data on that modem didn't require reliability, but some of
it did. So, by implementing a reliable UDP, I can control the timing,
resends, etc. In my situation, UDP is far better than TCP, because my UDP
packets left no room for the TCP packets.
I think that the bottom line is that TCP isn't a good choice for a game
unless you have plenty of bandwidth available for your requirements. Of
course, YMMV.
--
Kevin Bentley
Outrage Entertainment/Parallax Software
DirectPlay uses Windows' TCP/IP protocol... does that mean it's dog slow, or
is there some stuff under the hood to speed things up? (Let's say we're
talking 28.8 modems). I'm curious because I added 2-player component to a
game of mine using DPlay, and it seemed to work okay over the modem. But I
may not have been stressing the connection all that much, as it was limited
to 2 players... then again, I had nothing to compare it with.
- Mike
DirectPlay allows you to selectively send with or without reliability
(DPSEND_GUARANTEED). I noticed that between two 28.8 TCP/IP connections
(over the internet) this made a significant difference in latency(>100s
of microseconds).
I didn't investigate too closely, but I can only assume that
DPSEND_GUARANTEED uses TCP/IP and ~DPSEND_GUARANTEED uses UDP/IP.
--
Jason Shankel,
Maxis, Inc.
email provider: p o b o x . c o m
user id: s h a n k e l
Good luck with that one, spambots.
Jason Shankel wrote in message <359038...@bottom.for.e-mail>...
>DirectPlay allows you to selectively send with or without reliability
>(DPSEND_GUARANTEED). I noticed that between two 28.8 TCP/IP connections
>(over the internet) this made a significant difference in latency(>100s
>of microseconds).
>
>I didn't investigate too closely, but I can only assume that
>DPSEND_GUARANTEED uses TCP/IP and ~DPSEND_GUARANTEED uses UDP/IP.
When I attended a DirectPlay session at CGDC last year, they claimed that
DP5 would have a built in reliable UDP. I am highly doubtful that they
actually followed through with it though.
Does anybody know here what DirectPlay understands under
reliable sending? It does it through TCP or in another manner?
Sergey Zabaryansky
http://www.users.lucky.net.ua/~zssoft/
[Computer Graphics] [Win32] [System Programming]
<snip nice talk about TCP vs. UDP>
>I think that the bottom line is that TCP isn't a good choice for a game
>unless you have plenty of bandwidth available for your requirements. Of
>course, YMMV.
Hear, hear - well spoken, Bruce. That's probably the best post in
this thread. I agree whole heartedly.
>DirectPlay uses Windows' TCP/IP protocol... does that mean it's dog slow, or
>is there some stuff under the hood to speed things up? (Let's say we're
>talking 28.8 modems). I'm curious because I added 2-player component to a
>game of mine using DPlay, and it seemed to work okay over the modem. But I
>may not have been stressing the connection all that much, as it was limited
>to 2 players... then again, I had nothing to compare it with.
I assume that "over the modem" means a direct connection between two
modems, rather than via the internet. If that's the case, then I'd
doubt that TCP was being used. That would be horribly inefficient for
a direct modem connection. Oh, wait, we *are* talking about
Microsoft, aren't we?
ROFL :)
Since we are talking about efficiency I might as well have my say on
TCP vs. UDP over dial-up..
Current implementations of PPP (the dial-up networking protocol used
to carry IP/IPX/NetBEUI/etc.) will *usually* provide VanJacobson header
compression for TCP/IP packets, reducing the packet header from 40 bytes
to around 3. This can make a *huge* difference to the performance of
a modem link when carrying the small data packets (typically 8-20 bytes)
used by games. UDP on the other hand, does not benefit from any header
compression since this is not yet ratified by the IETF (RTP will do it)
so the modem has to carry 28 bytes of baggage on every packet. On the
third hand (how many have I got anyway?), most people enable error
correction & compression on their modem (but don't rely on it :), which
will partially compress UDP/IP headers (depends on the modem)...
DirectPlay 5 uses TCP/IP for gauranteed messaging, UDP/IP for datagrams
in the Winsock/IP service provider. It uses SPX/IPX datagrams in the
Winsock/IPX service provider (SPX=gauranteed messages). It may use a
proprietary protocol in the Serial/Modem service provider, which is more
efficient than TCP/UDP/IP/PPP, but I don't know for sure.
<PLUG>
Wireplay uses it's own serial port driver(s) and a proprietary protocol
to achieve low-overhead datagram delivery for fast action games. Since
we also manage the modem settings we can rely on V42bis to provide error
correction in hardware which is better tuned for congested links than
TCP will ever be, and some compression (although there is very little
that can be compressed in most game data).
We can also use TCP/IP, using the VJ header compression to maintain
link efficiancy, while avoiding re-transmission problems by careful
tuning of the TCP/IP software at our servers...it's not as good as the
proprietary solution but it's usually better than "the Internet"..
</PLUG>
--
!--------------------------- Phil "Phlash" Ashby ---------------------!
! BT Wireplay - Lead Programmer and general technical trivia supplier !
! Phone: 01473-644348 WWW: http://www.wireplay.com/ !
! Snail: B81/G41, BT Labs, Martlesham Heath, Ipswich IP5 3RE, England.!
> I think that the bottom line is that TCP isn't a good choice for a game
> unless you have plenty of bandwidth available for your requirements. Of
> course, YMMV.
Well said, I couldn't agree more. The technique you describe is exactly
what I did in my last game (SubSpace).
JeffP
> There are big advantages to doing your own error
> correction :)
Yes, there are. But you can get so hung up trying to beat a nearly
intractible problem that you'll never get your game done. Using UDP
instead of TCP will marginally improve gameplay over less reliable
circuits. The bottom line is UDP won't make typical 1 or 2 second
lags acceptable if they occur very often.
In practice if you use TCP you'll end up packetizing the data that
travels over the stream socket. You can use TCP to concentrate on
getting every other aspect of your game tweaked and playable. When
all that's done you can write your own reliability layer that improves
on TCP in-order guaranteed delivery. If you can afford to drop a
packet and ignore it, or accept and use them out of order, then you
can take care of that in a modular form.
You can even code for packet loss and out-of-order but not have to
deal with it actually happening until you know everything else is working.
Someone else called duplicating TCP a 'wooly' undertaking. It is. You
won't get it right the first time either. Better to know everything
else is working correctly by using TCP, then going back and writing
your own TCP replacement. At least if it screws up at that point you'll
know it's due to your packet delivery layer and not something else.
David Springer
--
*************** IGAMES INTERNET GAME LOBBY ****************
* *
* NOW SUPPORTING MICROSOFT DirectPlay 3 LOBBY STANDARD ! *
* *
* A real-time game lobby for the internet with many *
* exciting games and thousands of players. Game *
* developers, players, and ISP's can try it out at: *
* *
****************** http://www.igames.com ******************
No, nothing will.
>In practice if you use TCP you'll end up packetizing the
>data that travels over the stream socket. You can use
>TCP to concentrate on getting every other aspect of
>your game tweaked and playable. When all that's
>done you can write your own reliability layer that
>improves on TCP in-order guaranteed delivery.
>If you can afford to drop a packet and ignore it, or
>accept and use them out of order, then you can take
>care of that in a modular form.
The problem is that this is a very different philosophy to
accepting packet loss as inevitable. Most if not all of
the networking code would depend on guaranteed
delivery, so with UDP you'd end up rolling your own
(inferior) version of TCP.
>You can even code for packet loss and out-of-order but
>not have to deal with it actually happening until you know
>everything else is working.
I'll agree that TCP makes prototyping easier for getting
the code up and running. I suppose it'd be handy to use
TCP and have some debug code to kill/delay/resend
game packets to test the performance of the game
under different network conditions. I still think UDP is
the way to go for action games, though
---
Russ
That depends on the protocol stack you use. I've personally *seen* stacks
waiting for this amount of time.
>Non blocking I/O is a requirement for games. Fortunately in Windows it's
>a no brainer to avoid blocking socket functions.
And portability goes out the window... But you're right: For Win only, MS
managed to come up with a nice thing.
>> If the resynching proves a problem, don't use it. Write your own, I'd
>> suggest a positive acknowledge scheme: if a packet arrivbes and it is not
>> corrupt (use a simple CRC on the packet) then send an "it's okay" message
>> back. If the packet didn't arrive, or it arrived corrupt, do nothing. If
the
>> sender doesn't receive an ACK within a certain time period, resend the
>> packet.
>
>It isn't quite that simple - especially when there's more than two
instances
>of a game trying to communicate. What happens when an ACK is lost ?
You resend the packet. The client recognizes (hopefully:-) that it's an old
packet and ACKs it again. (And all packets received in the mean time also)
>Do you
>ACK the ACK ? A more efficient method is to number the packets and have
>the receiver NACK a specific packet number if it doesn't arrive.
That could make a nice extension to a windowing protocol, yes.
>There's no really good answer to any of this and UDP or TCP is the least
>of your problems if you have a high latency connection. The best thing
>to do is simply write it for a reasonable latency environment - 200 ms
>packet transit time - using TCP and advise players they need to take
>measures to ensure low latency.
Great. That may work for card games. I assure you you will not be able to
get e.g. an FPS game running over the Internet in a decent way by using TCP.
>A latency test across all required circuit paths prior to game launch
>works well so players with poor interconnectivity can avoid getting into an
>unsatisfactory game. A latency indicator that continues to function
>during gameplay is good too.
Definitely. And easy to obtain, if you've got a constant packet stream. Just
time how long it takes for an ACK to arrive.
Bye,
Robert
>The problem is that this is a very different philosophy to
>accepting packet loss as inevitable. Most if not all of
>the networking code would depend on guaranteed
>delivery, so with UDP you'd end up rolling your own
>(inferior) version of TCP.
Consider this. TCP requires packets arrive in order. If a packet gets
dropped somewhere in the pipe, all the following packets are blocked until
the lost packet can be resent. You can program around lost packets, but to
lose all communications because of one dropped packet is a little heavy.
Ideally, you should use more than one socket for communications. UDP for
data that can be made atomic within a UDP packet. TCP for data that is
position/order dependent.
Note: I believe that when IP was cooked up, the designers used Ethernet as
the default/generic network model when they designed the packets. This
leaves around 500 bytes per packet for game data.
Yup. That's why I'm anti-TCP for games. It's totally the
wrong tool for any kind of real-time system - games or
streaming.
>Ideally, you should use more than one socket for
>communications. UDP for data that can be made
>atomic within a UDP packet. TCP for data that is
>position/order dependent.
I'd say UDP for both. There are better ways to correct
for dropped packets than waiting for a TCP resend.
By simply increasing redundancy a little, you can
greatly reduce the need for resends - but you need to
take account of losing packets all through the network
code. It's no good if your game locks up waiting for
the next packet.
BTW - One thing about redundancy within packets.
If you send the same data in, say, 3 consecutive
packets, then the V.42bis (aka LZW) compression
on most modems should remove almost all of the
extra data. Cool :)
---
Russ
>Consider this. TCP requires packets arrive in order. If a packet gets
>dropped somewhere in the pipe, all the following packets are blocked until
>the lost packet can be resent. You can program around lost packets, but to
>lose all communications because of one dropped packet is a little heavy.
>Ideally, you should use more than one socket for communications. UDP for
>data that can be made atomic within a UDP packet. TCP for data that is
>position/order dependent.
True the application won't get that packet until the lost packet is resent.
However the sender uses a window of data. It will keep sending data, and the
receiving application will store that data until the missing packet arrives,
then it re-assembles the data and passes it up the the application. So one
lost packet might result in a small delay, but it the pipe is still working
in the mean time. The result is that you will get a large amount of data all
at once. This usually happens so quickly that the application doesn't notice
it though. Before telling me how bad TCP is for games, please read my
previous post on the subject. :)
>Note: I believe that when IP was cooked up, the designers used Ethernet as
>the default/generic network model when they designed the packets. This
>leaves around 500 bytes per packet for game data.
The maximum frame size for an Ethernet packet is 1518 bytes I believe. Since
UDP uses 34 bytes (including the Ethernet header) That leaves 1484 bytes for
data. However, if you send packets that large over a 28.8 modem, you will
max out at 1.5-2 packets per second, so sending packets that large isn't the
best idea. :)
Instead of the positive ack schema described earlier, you could (and
probably should) use a piggy-back ack schema if there are packets
going in both directons fairly often.
Every packet of data sendt to the other side will then also contain
acks for the packets received before, or possibily nack on the packets
missing in the sequence. You can have a look at the source for XPilot
for an example of such. <URL:http://www.xpilot.org/>.
--
##> Petter Reinholdtsen <## | pe...@td.org.uit.no
>>> >Well, yes. But be aware that the loss of a packet can lead to resynching
>>> >times in the range of 2-5 minutes, basically blocking your process in
>the
>>> >meantime. (Unless you use non-blocking I/O, but even then it would be
>>> simply
>>> >too long for a game).
>>
>>Huh ? A TCP connection will give up long before that much time has
>>elapsed.
>
>That depends on the protocol stack you use. I've personally *seen* stacks
>waiting for this amount of time.
Actually, IIRC, it depends on the KeepAlive value supplied, and
therefore varies by implementation. If a stack limited me on this,
I'd be quite unhappy.
>>Non blocking I/O is a requirement for games. Fortunately in Windows it's
>>a no brainer to avoid blocking socket functions.
>And portability goes out the window... But you're right: For Win only, MS
>managed to come up with a nice thing.
It's also a no-brainer in BSD sockets. We can only thank Microsoft
that we don't have to use the same no-brainer method everyone else in
the world uses...
Petter Reinholdtsen wrote in message <6mufbq$cum$1...@news.uit.no>...
>Instead of the positive ack schema described earlier, you could (and
>probably should) use a piggy-back ack schema if there are packets
>going in both directons fairly often.
>
>Every packet of data sendt to the other side will then also contain
>acks for the packets received before, or possibily nack on the packets
>missing in the sequence. You can have a look at the source for XPilot
>for an example of such. <URL:http://www.xpilot.org/>.
I try to make it a rule to make the far majority of the data that is sent
unreliable. In otherwords probably 95% of the data is sent through the
unreliable layer. I don't know how long it might be until the peer needs to
send me a packet back, so it would be inefficient to use a piggyback ACK. In
another situation it might be a good idea though.
Maybe if you get lucky. The standard implementation of TCP/IP a few
years ago had no support for this. Acknowledgement of packet X
meant acknowledgement of all packets before packet X. Thus there
was no way to say "I missed packet X, but have received packet
X+1, X+2, etc.". Thus, the normal behavior of TCP was to resend
everything after a dropped packet.
Now, I've seen the RFCs for doing this differently, actually tracking
which packets are missing and only requesting those, but I've
never been able to figure out if this extension has been deployed
at all, much less widely deployed.
You sound like it has, but I don't know if you're
just assuming it works that way, or you know for a
fact it works that way.
Sean
>
>True the application won't get that packet until the lost packet is resent.
>However the sender uses a window of data. It will keep sending data, and the
>receiving application will store that data until the missing packet arrives,
>then it re-assembles the data and passes it up the the application. So one
>lost packet might result in a small delay, but it the pipe is still working
>in the mean time. The result is that you will get a large amount of data all
>at once. This usually happens so quickly that the application doesn't notice
>it though. Before telling me how bad TCP is for games, please read my
>previous post on the subject. :)
In a real time game this time compression results in jitter and
choppiness. Perhaps the "application doesn't notice" but the user
certanly does.
>The maximum frame size for an Ethernet packet is 1518 bytes I believe. Since
>UDP uses 34 bytes (including the Ethernet header) That leaves 1484 bytes for
>data. However, if you send packets that large over a 28.8 modem, you will
>max out at 1.5-2 packets per second, so sending packets that large isn't the
>best idea. :)
The maximum is not what you want because it will be broken up at a
lower layer. The minimum will also be padded. What we want is the
ideal size. ( yes, I know there isn't really a true ideal, but the PPP
implementations I have seen use the approx. 500 byte packets also.
-----------------------------------------------------------------------
John Tessin (jte...@skygames.com) Phone: (619)627-9407 x167
http://www.geocities.com/CapitolHill/1685 Fax: (619)627-0717
Comments and opinions are mine and in no way represent the opinions of
BlueSky Software. IOW - I think for myself, even when I don't think.
-----------------------------------------------------------------------
It's not a big problem (if you know your CS) to make "tcp" versions over udp
that are much better for a given application (a game). It's true that Joe
Highschool perhaps better use TCP for it but it's really not rocket science.
We have a reliable, multiplexing, international system of UDP connected
servers that beats the shit out of any TCP if there is any packet loss
whatsoever, and there usually is across the atlantic etc.
/Bjorn
Yup. UDP rules. I was just saying that if you write the
game using TCP and then try to swap, you'll end up
trying to clone TCP. It's a very different philosophy
from expecting packets to arrive in order, to handling
packets not arriving.
---
Russ
Luck has nothing to do with it. If your definition of a few years is around
20 then maybe so. Otherwise, read the RFC and you will see differently.
>Now, I've seen the RFCs for doing this differently, actually tracking
>which packets are missing and only requesting those, but I've
>never been able to figure out if this extension has been deployed
>at all, much less widely deployed.
Well, windowed sends have been around since the early 1980's. In fact if you
read RFC813, you will see it described in detail. That RFC is dated 1982,
and that RFC has been the standard for TCP ever since. You can not only rely
on TCP using a window for sending packets, but you can rely on TCP
automatically adjusting the window size based on the current connection
(Added after rfc813).
>You sound like it has, but I don't know if you're
>just assuming it works that way, or you know for a
>fact it works that way.
I am not making any assumptions. As I said in my original post there are a
lot of misunderstandings/myths about TCP. I have made it a point to learn
the internet protocols very well, so I can leverage them in games that I am
working on. I suggest that people who are posting about internet protocols
or anything for that matter check their information before posting. It
doesn't do anyone any good to spread misinformation.
Kevin Bentley
Okay, is there a basic idea here to handle packets that don't arrive?
Certain packets must get through (eg, object destroyed/created, game starts,
other player enters game...). If those aren't received, the client will get
way screwed up. Does this imply that you must send "acknowledgement"
packets back to the server, so that it can re-send critical messages that
weren't received? (wait.. what if the "acknowledge" packet gets lost?...
eww,
this brings up a lot of tricky problems)
I can see getting away with missed packets in terms of updating positional
info (if missed, the object might appear to be in a false location, but will
probably be corrected on the next packet that DOES get through).
How about a mix of TCP/UDP -- TCP for absolutely necessary packets, UDP for
packets that are allowed to get lost..?
- Mike
PS -- just read Jonathan Blow's article in Game Developer. Good piece,
certainly gives one a lot to think about latency workarounds.
*No* packets 'must get through'. The net doesn't route
'important' packets differently.
>If those aren't received, the client will get way screwed up.
Not necessarily. If the client doesn't get the data, yes.
If the client gets the data late it's bad, too.
>Does this imply that you must send "acknowledgement"
>packets back to the server, so that it can re-send critical
>messages that weren't received?
No. That's one way, but it's not the only way. This is what
I was saying - if you rely on TCP for development you
get locked into the 'packets must/will arrive' mindset.
>(wait.. what if the "acknowledge" packet gets lost?...
>eww, this brings up a lot of tricky problems)
Yup. The solution for that is for both the client and server
to keep repeating the last packet until they recieve the
appropriate packet from the other end. A data packet
is answered with an ack, an ack is answered with a
data packet. Unfortunately, this gives you half-second
latencies...
>I can see getting away with missed packets in terms of
>updating positional info (if missed, the object might appear
>to be in a false location, but will probably be corrected on
>the next packet that DOES get through).
You need to make sure the data gets through, even when
packets are lost.
Here's a pretty good way:
Packets: [Aa] [Bb] [Cc] [Dd] [Ee] [Ff]
(Upper case = important data, lower case = unimportant)
If one of those packets gets dropped, you're in trouble.
What if you sent these packets?
( [Aa] ) [ABb] [BCc] [CDd] [DEe] [EFf] ( [F] )
Losing any one of those won't matter - the important data
arrives in the next packet. No resends or ACKs.
>How about a mix of TCP/UDP -- TCP for absolutely
>necessary packets, UDP for packets that are allowed
>to get lost..?
Wouldn't stop TCP being too slow. Besides, what if the
TCP packet specifiying an object's creation needs to
be resent, and UDP packets referencing it arrive first?
Lots of work to make it bulletproof.
[...]
>PS -- just read Jonathan Blow's article in Game
>Developer. Good piece, certainly gives one a lot to
>think about latency workarounds.
Haven't read it. I should get a GDMag subscription...
---
Russ
Russ Williams wrote:
> Here's a pretty good way:
> Packets: [Aa] [Bb] [Cc] [Dd] [Ee] [Ff]
> (Upper case = important data, lower case = unimportant)
> If one of those packets gets dropped, you're in trouble.
> What if you sent these packets?
> ( [Aa] ) [ABb] [BCc] [CDd] [DEe] [EFf] ( [F] )
> Losing any one of those won't matter - the important data
> arrives in the next packet. No resends or ACKs.
Yeah, but assuming 1 in 20 packet loss, you still have
unrecoverable errors every 400 packets. Sending
critical data in three packet sequences lowers your
risk to 1 in 8000, theoretically. Keep in mind that
you often lose _a lot_ of packets in sequence. You
need some sort of resynchronization mechanism there
anyway. This mechanism could provide a useful
adjunct to a resync mechanism to keep it from firing
too often, though.
On another note, has anyone actually done any
_testing_ (I'm talking real, honest to goodness
tests here, not idle supposition (unless you are
from a modem manufacturer and know for sure))
of the efficency of modem compression when the
critical data is resent 2 or 3 times?
--
Acy James Stapp - Slam Software - Amp 3D Engine
ast...@slamsoftware.com http://www.slamsoftware.com
--
Every U.S. Citizen (and others) should read and think about:
http://www.house.gov/Constitution/Constitution.html
http://www.law.indiana.edu/uslawdocs/declaration.html
Then read:
http://www.cwrl.utexas.edu/~bill/e309m/3rd/shoemake/ethics_on_the_net/restrictions.html
Wouldn't the Declaration of Independence, if written today, be
considered
"conspiracy to overthrow the government of the United States?"
I know, it's just that I couldn't be bothered typing more ;)
It's probably worth setting the number of consecutive
packets to 1 or 2 more than the most lost in the last
minute. That way, it should adapt to the condition of the
connection.
>Keep in mind that you often lose _a lot_ of packets in
>sequence. You need some sort of resynchronization
>mechanism there anyway. This mechanism could
>provide a useful adjunct to a resync mechanism to
>keep it from firing too often, though.
If you lose n consecutive packets, the connection is
screwed. There's nothing you can do except wait
for the connection to be restored, so you might as
well have a 500ms timeout and then panic and
start sending NACKs until you either reach the
server or hit the auto-disconnect timeout.
>On another note, has anyone actually done any
>_testing_ (I'm talking real, honest to goodness
>tests here, not idle supposition (unless you are
>from a modem manufacturer and know for sure))
>of the efficency of modem compression when the
>critical data is resent 2 or 3 times?
I haven't, but I'd assume that it'd work as well as LZW
normally would.
---
Russ
You know, one thing strikes me, and that is that all of this is taught in CS
educations, including much about how to make reliable connections and what
quantitative measurements you should use to check on latencies and bandwidth
etc. But at the same time people here actually advocate NOT going through an
engineering education. That strikes me as funny and this is a good example
of why you want to go to school :)
There are numerous other examples of things you actually DO learn in CS
educations that you don't normally learn by hacking assembler on your Amiga
(been there! :)). So don't scoff at universities!
(not directed at you russ, just an observation!)
/Bjorn
You are both right and wrong :) it is true that the receiver can't
(normally)explicitely tell the sender "I missed packet X" (selective
acknowledgment). BUT, the sender can realise this due to the way TCP is
required to ACK every out of order packet. So if the receiver misses a
packet, it will consider all other packets to be out of order, which causes
an ACK to be sent for each packet. Therefore, if the sender suddenly sees a
lot of ACK's for the same sequence number coming, it can realise this might
be because of the loss of a certain packet.
What then happens is that the sender retransmits that packet even if that
packets retransmit timer hasn't expired, _and then continues where it was
stopped_ instead of retransmitting everything from that packet and upwards.
This is called the Van Jacobson fast retransmit algorithm and was proposed
on April 30 1990, hardly 20 years ago.
>>Now, I've seen the RFCs for doing this differently, actually tracking
>>which packets are missing and only requesting those, but I've
>>never been able to figure out if this extension has been deployed
>>at all, much less widely deployed.
This is true.
The fast retransmit algorithm covers for the case of moderate packet loss;
one packet lost per window. Jacobson has proposed, several times (RFC 1072,
RFC1323 etc), actual TCP options to implement selective retransmission, but
they have been too complex to implement in practise. I quote from RFC 2018
as of october 1996 (SACK = selective ACK):
"RFC 1072 [VJ88] describes one possible implementation of SACK options
for TCP. Unfortunately, it has never been deployed in the Internet,
as there was disagreement about how SACK options should be used in
conjunction with the TCP window shift option (initially described
RFC 1072 and revised in [Jacobson92])."
Then they go on suggesting some improvements on this, but I doubt that this
algorithm (of 1996) is implemented in practice anywhere. Someone might fill
in something here - i crossposted to comp.protocols.tcp-ip.
>Well, windowed sends have been around since the early 1980's. In fact if
you
>read RFC813, you will see it described in detail. That RFC is dated
1982,
We are talking retransmit algorithms here, not receiver based window flow
control, which is the main point of RFC 813.
>but you can rely on TCP
>automatically adjusting the window size based on the current connection
>(Added after rfc813).
You probably mean the congestion window control.
>>You sound like it has, but I don't know if you're
>>just assuming it works that way, or you know for a
>>fact it works that way.
>
>I am not making any assumptions. As I said in my original post there are a
>lot of misunderstandings/myths about TCP
But you misunderstood the issue discussed I guess.
Having the bible (Stevens) and reading RFC's are good ways to know tcp/ip,
yes.
/Bjorn
>You are both right and wrong :) it is true that the receiver can't
>(normally)explicitely tell the sender "I missed packet X" (selective
>acknowledgment). BUT, the sender can realise this due to the way TCP is
>required to ACK every out of order packet. So if the receiver misses a
>packet, it will consider all other packets to be out of order, which causes
>an ACK to be sent for each packet. Therefore, if the sender suddenly sees a
>lot of ACK's for the same sequence number coming, it can realise this might
>be because of the loss of a certain packet.
I won't quote the whole thread because it's getting a bit long. However, if
you watch the behavior of TCP you will see that it doesn't blindly
retransmit all the packets that haven't been ACK'd. If it doesn't get an ACK
in whatever the current retry time is (1 or more seconds) it will send the
smallest sequence number it has not been acked for, then wait a period of
time before sending any more packets. It is true that there is no way of
saying "I missed packet x", but it doesn't matter because TCP will not keep
resending all the missed packets all at the same time. So in a case where
you received packet 1,3,4,5,6,7 but not packet 2, the sender will not
immediately retransmit packets 2-7. It will send packet 2, then give the
receiver a chance to ACK with the highest sequence received. There is a lot
of timing issues involved.
Windowed sends were created to improve throughput, and that is the issue
which was raised. My point was that windowed sends have been around for
nearly 20 years in TCP.
Kevin Bentley
Hmm... so I can pay $1000s/year for tuition, or post a few relevant
questions here... tough choice :)
- Mike
Wow, that's a lot of sending.
>>I can see getting away with missed packets in terms of
>>updating positional info (if missed, the object might appear
>>to be in a false location, but will probably be corrected on
>>the next packet that DOES get through).
>
>You need to make sure the data gets through, even when
>packets are lost.
>
>Here's a pretty good way:
>Packets: [Aa] [Bb] [Cc] [Dd] [Ee] [Ff]
>(Upper case = important data, lower case = unimportant)
>If one of those packets gets dropped, you're in trouble.
>What if you sent these packets?
>( [Aa] ) [ABb] [BCc] [CDd] [DEe] [EFf] ( [F] )
>Losing any one of those won't matter - the important data
>arrives in the next packet. No resends or ACKs.
Huh. neat. That solution assumes you'll never lose 2 packets in a row (or
as Acy said, you could use 3).
Hmm.. even if you *did* lose one, like if the game misses a 'create'
message, then starts to get updates for it, I suppose it could send a
request to retrieve the 'create' message for that object again... likewise,
an object that doesn't receive an update beyond a certain deadline could
request an update... possibly to verify that it had been destroyed. That
should handle most of the critical message screw-ups. I guess any message
types can have their own special-case precautions.
>>How about a mix of TCP/UDP -- TCP for absolutely
>>necessary packets, UDP for packets that are allowed
>>to get lost..?
>
>Wouldn't stop TCP being too slow. Besides, what if the
>TCP packet specifiying an object's creation needs to
>be resent, and UDP packets referencing it arrive first?
>Lots of work to make it bulletproof.
I was thinking about this when I wrote my last paragraph. But as you say,
if you can handle UDP some of the time, you might as well handle it all the
time.
Thanks for the tips.
- Mike
Yes that is the Van Jacobson [1990] fast retransmit algorithm I described.
It only works if you have up to one packet loss per window though, granted
that is a quite normal case.
>Windowed sends were created to improve throughput, and that is the issue
>which was raised. My point was that windowed sends have been around for
>nearly 20 years in TCP.
Yes without windows TCP would stand still on connections with large
bandwidth*delay numbers.
/Bjorn
David Springer wrote in message <6msblk$n68$1...@boris.eden.com>...
>Russ Williams (ru...@algorithm.demon.co.uk) wrote:
>
>> There are big advantages to doing your own error
>> correction :)
>
>Yes, there are. But you can get so hung up trying to beat a nearly
>intractible problem that you'll never get your game done. Using UDP
>instead of TCP will marginally improve gameplay over less reliable
>circuits. The bottom line is UDP won't make typical 1 or 2 second
>lags acceptable if they occur very often.
>
>In practice if you use TCP you'll end up packetizing the data that
>travels over the stream socket. You can use TCP to concentrate on
>getting every other aspect of your game tweaked and playable. When
>all that's done you can write your own reliability layer that improves
>on TCP in-order guaranteed delivery. If you can afford to drop a
>packet and ignore it, or accept and use them out of order, then you
>can take care of that in a modular form.
>
>You can even code for packet loss and out-of-order but not have to
>deal with it actually happening until you know everything else is working.
>
>Someone else called duplicating TCP a 'wooly' undertaking. It is. You
>won't get it right the first time either. Better to know everything
>else is working correctly by using TCP, then going back and writing
>your own TCP replacement. At least if it screws up at that point you'll
>know it's due to your packet delivery layer and not something else.
>
>David Springer
>
>--
>
>*************** IGAMES INTERNET GAME LOBBY ****************
>* *
>* NOW SUPPORTING MICROSOFT DirectPlay 3 LOBBY STANDARD ! *
>* *
>* A real-time game lobby for the internet with many *
>* exciting games and thousands of players. Game *
>* developers, players, and ISP's can try it out at: *
>* *
>****************** http://www.igames.com ******************
>
>If you lose n consecutive packets, the connection is
>screwed. There's nothing you can do except wait
>for the connection to be restored, so you might as
>well have a 500ms timeout and then panic and
>start sending NACKs until you either reach the
>server or hit the auto-disconnect timeout.
Good point, but I have something further to add (as
someone who has actually worked on a completed system
where this is done!)
It often happens over a modem that you get heavy line
noise or some other communications problem that,
effectively, causes a blackout of a substantial period
(from .5 seconds to several seconds) during which you
can neither send nor receive data, as described
above...
...except that due to the nature of the interference,
the NACKs probably won't get through either. The
only real way to handle this situation is for each
end to realize that it hasn't heard anything from
the other in a little while, and go into some kind
of emergency handling mode.
Probably for the server the best method of emergency
handling is to *not send any data at all*, not even
pings. This is because the server is usually buffered
from the actual server-side modem by a reasonable
amount of equipment, which seems to have the
undesirable effect of buffering up outgoing data
from the server end until it can be sent (even if
it's stuff like UDP packets, which could be dropped).
This means that when the blackout is over, now you
get a flood of *old data* coming in over the modem,
and your game gets a hangover. Thus there is a period
after the blackout when no new data can be received,
because old buffered-up data is still trickling
through.
If the server detects this situation soon enough, it
can choke the outgoing stream to that client. The
client, when it realizes it hasn't gotten data in
a while, starts pinging the server with a special
recovery signal. (The client's upchannel usually
is not nearly so clocked as the other, so we feel
better about sending pings over it). Once the
server receives a recovery signal that is not very
lagged, it restarts the normal flow of communication.
Through doing this, we have been able to cut the
post-blackout sludge period by about half or
two-thirds.
Jonathan Blow
Bolt Action Software
PS: I was going to talk about this kind of thing in
the Game Developer article, but that article was
already damn well big enough.
Or live in a country where all tuition is free :)
(there are free universities in the US as well aren't there?)
/Bjorn
"That was the issue which was raised"? Windows were created to
improve throughput ignoring the presence of packet loss. As far
as I know (although various people have deleted the context), we
were explicitly talking about the latency caused by packet loss.
Note what you say above:
"it will send packet 2, then give the receiver a chance to ACK with
the highest sequence received"
So, while it's sitting there waiting for a *complete* roundtrip
to ACK packet #2, it's sitting there *not* using any bandwidth.
Now, I *wish* you would have just responded to my email
to take this offline until we figured out what the source
of our disagreement is. I don't like to "calling you down" in
public like this. But I don't want you operating from a position
of apparent authority (a network programmer at a high-profile game
company) spreading misinformation, either.
Here are the possible scenarios for various plausible network
protocols, after the sender decides to resend #2:
A: sender goes ahead and sends #3, #4, etc.
The problem with this is that since nothing has been
ack'ed since #1, if you stick with a pure windowing
scheme, then the sender doesn't believe there's
any room for any data in the pipe. In other words,
this is impolite in the face of insufficent bandwidth
to deliver all the data.
B: sender goes ahead and sends #8, #9, etc.
The reason this won't happen in real life is the same
as above. It also assumes that no other packets have
been lost. It is *possible* for this to work, if the
receiver is willing to hang onto out-of-order packets
to arbitrary depths.
C: sender waits for an ack so it knows where to pick up.
After packet #2 gets there, the receiver acks up to #7,
and can immediately process #2-7. At the conclusion
of one round trip time, the sender gets the ack for #7,
and can send #8. Thus, there is a 1 round-trip delay
between when packet #8 gets there for C vs. B.
D: receiver sends along a "selective" ack so the sender
knows which other data to send, and we proceed from #2,
thus achieving the same performance as B but without
doing it by "guesswork".
Note that if the windowing is independent of the acking,
then the receiver can at least give windowing feedback
for the packets it has received, enabling A or B to happen.
Thus, the actual TCP protocl is well and good for a protocol optimized
around making sure the data gets there, and making sure it
*plays well with others*. I'm really worried about people
writing their own reliable protocols on top of UDP that
don't use play well with others (e.g. backing off).
But then again, the whole concept of the web is "screw
trying to make efficient use of bandwidth, let's just
send everything to everybody separately" (as opposed
to Usenet (huge numbers of local servers) or IRC (a
significant number of servers). So maybe playing well
with others is less important these days.
Anyway, the whole backing-off / waiting round-trips
is good for high bandwidth utilization at the routers,
and bad for latency on individual systems. A reliable
protocol on top of UDP with selective acknowledgement
might me more appropriate for a game, especially if you
know that the bandwidth requirements for the reliable
channel are low enough that that infrastructure in TCP
is irrelevent, and that you want to avoid the latency.
Sean
First off, TCP will attempt to time the amount of data it sends out by
timing the incoming ACKs and determining the optimal amount of data it can
send.
Yes, but my point is that it *isn't* resending packet 3,4,5 blindly. I admit
there is some loss of throughput. I was simply saying that with windowed
sends the following doesn't happen (ok, in most cases it doesn't happen):
Sender sends 1,2,3,4,5. Client receives 1,3,4,5, and ACKs 1 as the last
received. Sender sends 2,3,4,5 again.
I am saying that this doesn't happen because of the timing of TCP. The retry
time is much higher than the round trip latency (usually) so by the time the
sender resends packer 2 and is ready to send packet 3, the client has time
to ACK sequence 5 as received. So the end result is that the sender doesn't
waste bandwidth by sending all the packets blindly. Even though there is no
individual ACK per sequence, there is timing to reduce additional resends.
>Now, I *wish* you would have just responded to my email
>to take this offline until we figured out what the source
[snip]
I didn't think we had a dissagreement after reading your email, and that's
what I was trying to say in my previous post. I was saying that windowed
sends have been around for along time. I got the (incorrect) impression from
your previous post that you didn't think that windowed sends were ever
implemented. I was speaking about windowed sends, and I thought you were
too. I'll admit that after re-reading your email I see that you were talking
about specific behaivor, where I was talking about actual throughput.
>Thus, the actual TCP protocl is well and good for a protocol optimized
>around making sure the data gets there, and making sure it
>*plays well with others*. I'm really worried about people
>writing their own reliable protocols on top of UDP that
>don't use play well with others (e.g. backing off).
>
>But then again, the whole concept of the web is "screw
>trying to make efficient use of bandwidth, let's just
>send everything to everybody separately" (as opposed
>to Usenet (huge numbers of local servers) or IRC (a
>significant number of servers). So maybe playing well
>with others is less important these days.
>
>Anyway, the whole backing-off / waiting round-trips
>is good for high bandwidth utilization at the routers,
>and bad for latency on individual systems. A reliable
>protocol on top of UDP with selective acknowledgement
>might me more appropriate for a game, especially if you
>know that the bandwidth requirements for the reliable
>channel are low enough that that infrastructure in TCP
>is irrelevent, and that you want to avoid the latency.
Just to be very clear here, I do agree with you on this. I don't think that
TCP belongs in most games either. I just think that at times TCP doesn't get
a good rap in general. In my reliable UDP layer, I selectively ACK each
packet, in part because I am sending so little data reliably that it isn't a
major bandwidth hit. Also because in my implementation I time my retries
more closely to the actual network latencies, I want to make sure the ACK
gets back right away, not waiting <200ms to send an ACK like TCP does.
--
Kevin Bentley
Outrage Entertainment
You need an extremely fast ping, if the sender should get the reply from the
resent packet 2 immediately after packet 2 is sent and it's ready to send 3
again (to make it realise it can skip up to 6).
As I've written perhaps 3 times now, what really happens is that the
receiver sends out ACK's every time an out of order packet is received. So
the receiver sends out an ACK[1] after it has received packet 1 (with a
small delay often), and then ACK[1] every time it receives packets 3, 4, and
5 because they are out of order.
Therefore, the sender will send packets 1,2,3,4,5, then receive TWO or more
ACK[1]'s, then it can draw the conclusion that packet 2 was lost, it resends
packet 2, and _immediately_ continues at packet 6 _without_ waiting for an
ACK. Otherwise it would have to sit dead until the real ACK[5] comes,
something that could take a very long time (several 10's of ms usually).
This is the VJ fast retransmit algorithm. See Stevens TCP/IP Illustrated
Volume 1, section 21.7, there are some nice graphs of tcpdumps from actual
implementations.
>Just to be very clear here, I do agree with you on this. I don't think that
>TCP belongs in most games either. I just think that at times TCP doesn't
get
>a good rap in general. In my reliable UDP layer, I selectively ACK each
Yup.. TCP was designed for working with bandwidths between 300 bps and 100
mbps, for interactive char-by-char sessions and filetransfers. It's done
extremely well, but it's no wonder that people get suspicious and think it's
best to write a case optimized UDP protocol. Sometimes this is better,
sometimes its not. As Sean said, an aggressive UDP protocol won't really
help congestion at overloaded routers. But at least, you have the option to
tweak each parameter yourself instead of relying on the kernel to make the
decision - especially since different kernel stacks perform differently. I
haven't measured myself, but many people seem to bash win95's tcp/ip
implementation. Congestion avoidance is a whole science in itself, if you
have the time, you can with no doubt tweak your parameters to optimize a
reliable link over udp for a special case compared to tcp.
Don't attempt this at home! :)
/Bjorn
Granted that UDP can improve playability on a marginal connection if
one puts enough work into being able to tolerate a small amount of
packet loss.
An issue that is perhaps larger in many circumstances is that incoming
UDP packets are blocked by most corporate firewalls while TCP connections
are allowed, provided that the connection attempt doesn't originate
from outside the firewall.
I was wondering if any of you had considered using RAW packets to gain
the advantage of UDP without the firewall problem. Most firewalls allow
raw packets in both directions.
I experimented with this about 2 years ago and found it was workable but
Winsock (back then) did not support the RAW protocol. Winsock 2 does, so
it's now a viable option (for Win95/98/NT platforms at any rate).
What do you mean by RAW packet?
/Bjorn
It's a protocol type SOCK_RAW. ICMP packets. It's what ping uses.
Winsock didn't provide documented support for it. If you disassemble
the Win95 ping utility you'll see some obtuse undocumented interfaces
used to obtain a SOCK_RAW socket.
Winsock2 has documented support for it. For more information try
http://www.hotbot.com and search for "SOCK_RAW"
Most firewalls allow pings to go through in either direction. You can
attach data to a ping and deliver it to an application instead of it
being automatically echoed. I experimented with it enough a couple of
years ago to know it was a valid workaround for incoming UDP blockage
in firewalls. Unfortunately my application was Win95 based and after
discovering that the undocumented winsock APIs could go away at any time
I set it aside as too risky to implement. Winsock 2 changes that.
I talked about it on this newsgroup at the time. The only reaction I
got was what a wanker I was for trying something so dastardly as using
ping packets to deliver application data across firewalls.
David Springer
> > What do you mean by RAW packet?
>
> It's a protocol type SOCK_RAW. ICMP packets. It's what ping uses.
Also, on Unix you need to be root or run setuid to create a raw
socket.
--
Acy James Stapp - Slam Software - Amp 3D Engine
ast...@slamsoftware.com http://www.slamsoftware.com
--
From the 1992 Presidential Campaign
Reporter: "Have you ever had an extramarital affair, governor [Clinton]?"
Clinton: "If I had, I wouldn't tell you."
If you mean ICMP packets, write ICMP - raw is _any_ packet. Some previous
poster claimed that "most firewalls let through RAW packets" which is a
quite erroneous statement - first, there is no such thing as a raw packet
(on the network), and second, if he meant icmp, most firewalls worth their
salt do NOT let through icmp's. In fact, most companies have completely
local IP adress families inside so the concept of reaching a computer inside
doesn't exist, apart from through a proxy.
/Bjorn
Actually the RFC-2018 tcp selective acknowledgement is fairly widely
available. E.g., it's a standard part Win98. A good summary of the
current state of things is:
http://www.psc.edu/networking/all_sack.html
In my recollection of events (which is colored by the frustration I felt
at the time) the difficulty in turning RFC-1072 into an Internet
standard (which was necessary to get wide vendor adoption) had nothing
to do with implementation complexity (the test implementation I had at
the time added ~40 lines to the BSD kernel). What I saw happening was
that a university professor decided that the addition of three new
things to TCP (window scaling, timestamps, sack) was a change large
enough to create doubt about the overall viability of TCP. With a
relatively small effort on the part of his group to promote & nurture
that doubt, he'd might be able suck a lot of money out of DARPA & NSF to
increase funding for his existing research into TCP alternatives. [This
strategy was eventually quite successful for him.] So he & his minions
mounted a *very* active campaign in the IETF TCP-LW working group to derail
the adoption of 1072. We had a weath of theoretical, simulation &
operational data supporting the window scale & timestamp options so they
didn't have much luck on that attack but we weren't as well prepared on
sack - there was 2 decades of ARQ research demontrating the
effectiveness of selective acknowledgment but they claimed it didn't
apply to TCP & at the time we didn't have the simulator technology to
show they were just blowing smoke. After 2 years of deadlock in tcp-lw,
we decided that some progress was better than none so we removed the
SACK stuff from 1072 & created a new RFC with just the window scale &
timestamp options (RFC-1323). It became a standard. We also started
putting the pieces in place to get the simulation & operational data
needed to push SACK forward. Much of the work on test implementations
was done a Pittsburg Supercompter Center by Matt Mathis & Jamshid
Mahdavi and they, in the course of their testing, made several
improvements to the sack algorithm in RFC-1072 and a variation on their
improved version eventually became an Internet standard with RFC-2018.
So the final result of the process was a better sack than the one we
would have had if greed hadn't derailed 1072 but I occasionally wonder
if it was worth the 8 year wait & associated confusion & mis-information
("sack is too complicated", etc.).
- Van