Archived

This topic is now archived and is closed to further replies.

The Great Sephiroth

UDP/IP Packets And Splitting...

Recommended Posts

OK, I have been toying with sockets for a while now, though primarily on my Linux boxes. Now however, since I am an avid GL and C/C++ coder in Win32, I have decided to take one of my older games and redo it in GL, and add multiplayer. I already have a lot of code to minimize network traffic, such as the server only sending data on other players that the player can physically "see", only sending data on world objects when they move, and not when they''re idle, etc etc. I am also restricting player chat messages to 256 characters. However, this is UDP and while a dropped packet should be no problem by itself, if a packet gets split, and/or arrives out of order, I am lost on what to do. So far I have a list of "impulses" that the server sends to the client, and another list that the client sends to the server. Each one means something different, such as 0 from the client means the packet contains connection info (version and CRC), while 0 from the server means that the client version and CRC are fine. Now for the problems I forsee. 1) How do I deal with a packet that gets split? 2) What if a split packet has one packet dropped? 3) In #2, how long do I wait to drop the whole thing? 4) Could I use "send()" and point it to a struct of floats to send the player''s position to the server?? I have some more minor questions, but those are the big ones. Thanks for the help!

Share this post


Link to post
Share on other sites
WebsiteWill    134
1, 2, 3) You detect that the entire packet didn''t arrive. When you send a packet over the net, another layer of the stack can divide this packet into frames. I think it''s the Data-Link layer. On the other side, the same layer reassembles the packet. If not all frames arrive then the whole packet is discarded. So you just ahve to check if your application receives the packet at all (if you care).
4) You can send pretty much anything you can create in C++. Everything is converted into a character stream before being sent. For character movements you would likely have some internal structure like this
struct Move
{
int iPacketType;
float fDeltaX;
float fDelyaY;
}sMoveData;

Then what you would send is simply
char* cpsMoveData = (char*)&sMoveData;
The structure cast into a character pointer.

Then on the other side you could have a generic structure that has just the type parameter like this
struct Generic
{
int iPackType;
} sGeneric;

And you would call recv or recvfrom with a pointer to a character array of some arbitrary size. Then you cast that char array into type sGeneric. Then you can access the type parameter and figure out what type of packet it is. It it is of type Move then you can recast it into a Move structure and voila you have access to the deltas that you need.

Hope this helps,
Webby

Share this post


Link to post
Share on other sites
Thanks, you REALLY cleared a lot of my worry up, but I want to be clear on just ONE thing before I off and go beyond this point. Even if some guy on a 14.4k modem sends a UDP packet that is say, "char Message[8192]", my "recv()" function on the server won''t get the packet until it has been COMPLETELY reassembled by the system? If that is the case, AWESOME. If not, I''m back to worrying about getting the first 256 chars on one recv() then the next 128 on another, etc etc.

My final worry is this. My server is setup to handle up to two-billion players (though I plan on limiting that on my current box and line). Needless to say, they''re all going to be constantly updating their positions and such. Is it possible that in a single "recv()" on the server, the server could get a whole packet from guy A and part or all of a packet from guy B? That''s about the only other worry I have, and since I am on a 200mbps ethernet connection to the server, I can''t simulate 56k speeds. Thanks for all your help!


-The Great Sephiroth

Share this post


Link to post
Share on other sites
T2k    220
maybe you want to use the max packetsize of udp packets and then manage them by you app !? this would reduce a resend of 8kb when only one 0,5kb packet is lost...

i think getsockopt with the optname SO_MAX_MSG_SIZE will give you the value for this, but its maybe something different (sorry ive begun network programming yesterday )


T2k

Share this post


Link to post
Share on other sites
I''ve been doing it for almost a year now, and I''m not sure if that works under Windows. I know you can''t set a non-blocking socket in Windows because fcntl.h contains DOS info, not socket. And the help on Winsock is VERY limited. MS just HAD to change things around on their OS, even if it was just capitalizing a name or something.


-The Great Sephiroth

Share this post


Link to post
Share on other sites
foofightr    130
quote:
Original post by The Great Sephiroth
I know you can't set a non-blocking socket in Windows because fcntl.h contains DOS info, not socket.



#include <winsock2.h>

...

// make non-blocking
u_long yes = 1;
retval = ioctlsocket(m_Socket, FIONBIO, &yes);
if (retval == SOCKET_ERROR)
{
...
}



[edited by - foofightr on August 31, 2003 7:57:42 PM]

Share this post


Link to post
Share on other sites
Yes but I thought winsock2 was incompatible (or didn''t work right?) on 95? I know it works on 98SE and later, but I was trying to code the engine to run on all platforms of Windoze. With just "winsock.h" I tried and could never get it to work though.

Share this post


Link to post
Share on other sites
krez    443
quote:
Original post by The Great Sephiroth
And the help on Winsock is VERY limited.

what are you talking about? i think the only thing that is more prolific than porn on the internet is winsock tutorials! try google, or even just the articles and resources section here at gamedev.net...

Share this post


Link to post
Share on other sites
Yeah, in "Visual ". I am not a Visual kiddie who uses IDEs because I don''t know anything about actual coding. I do 100% of my work in Wordpad. I''m not trying tod iscourage new programmers from using these Visual IDEs, because they are a GREAT newbie utility, and would have helped me way back when I started coding for the 6502 chips (1.8MHz Atari 400/800 chips). However, in dead-on comparisons, the applications produced by these Visual IDEs generally get MUCH lower performance than hand-coded ones because they are not optimized and the code is often VERY sloppy and hard to follow.

Anyways that''s off-subject. I am doing this app primarily in C, and since most tutorials or infos on Winsock are for Visual C++ or Visual Basic, they''re useless to me. I''ve toyed with C++, but it''s useless if you already know C. The way I see it (and have proved to several friends) is this: Your harder to follow C++ code simply gets converted to plain old-fashioned C before being compiled, so if you know C, stick with it. C is easier for most people to follow anyway. And the whole "classes and inheritance is a C++ thing" is a myth. A class and a struct are identical, only the struct has all members public by default, whereas a class makes them private by default.

Sorry if I rambled here, didn''t mean to. I have looked for tutorials and the only one I found that was what I was looking for was here. It was the first one listed, by Beej. It''s what I used to get into coding TCP/UDP. Very easy to follow, in plain C, and it is ANSI so it works on Windoze or Linux. It''s hard finding good tutorials like that any longer. That''s why I regular this site and the one I admin three boards at. I don''t know if I should post the site name/address here though, because I don''t want to get in trouble for spam :D!

-The Great Sephiroth

Share this post


Link to post
Share on other sites
foofightr    130
Good thing this is not a very frequented forum, because you opened up a can of worms... several cans, in fact. Suffice to say I think you''re wrong about a lot of things...

What I will say is this. Even if winsock2.h isn''t available on Win95, who cares? It''s a dead platform, even Microsoft has stopped supporting it. The only people who still use it are people who don''t know any better.

Share this post


Link to post
Share on other sites
True, but I know some of those people! I personally run DOS6.22 and Win3.11For Workgroups on my 286 and 486, and then 98SE on my P133, P2/233, and P3/866, and then XP on this P4/3.56. I also run Debian Linux on a Celeron333 and a P200. Game server and FTP server respecitvly. The only real reason I run XP is because I *HAVE* to, to take advantage of my P4. I tried 98SE on this box originally since it is the best Windows OS (largest memory block size, fewest page faults, etc) for gaming (which I do plenty of), but even with the 98SE patches, it shut down so fast data was being lost, it was HORRIBLY unstable for some reason, and it just ran like crap. I guess like if I had a Cyrix chip!

Anyways I did some looking and I think Winsock2 is supported on 95 if you have about a gig of patches, haha! I''lljust code for 98SE and beyond.

-The Great Sephiroth

Share this post


Link to post
Share on other sites
cbenoi1    484
> Even if winsock2.h isn't available on Win95

You can upgrade 95 with winsock2 here. But you can use the older winsock 1.0 specs and header since you are not using the more advanced winsock2 API anyway. Winsock2 is only required if your machine is to become a client of MS SQL Server 2000 and up. Not your bag, I can tell.

> I personally run DOS6.22 {...}

Yeouch! Reminds me of the good ol' days when I ported SGI's GL (OpenGL's precursor) to Windows 1.04. The VGA was too much a novelty then and we had to use the old EGA. What a mess...

-cb

[edited by - cbenoi1 on September 1, 2003 9:08:41 AM]

Share this post


Link to post
Share on other sites
RonHiler    214
quote:
Original post by foofightr
Suffice to say I think you''re wrong about a lot of things...


Indeed. It''s been a while since I''ve seen so many statements I disagree with in one paragraph

Share this post


Link to post
Share on other sites
Sounds like you''re a fan of the Visual tools ! I wasn''t trying to bash them to nothing, because they''re a GREAT way for a novice to visually make a window and then look at the code that actually does the work. I remember when I started Win32 coding, I''d have to calculate the crap in my head and visualize it in there too! Sometimes that got annoying, but I got it down after a while.

However, and I don''t care what ANYBODY says because it''s been proven time and again, Visual versions of the same languages are always slower than if the same app was done by hand. The code is almost ALWAYS less organized (hey, it''s a nice app but it isn''t human AI in there), and if you open a Visual app in any text editor (the sources you''re working on, that is) you will see a bunch of extra includes that your app does not need, that are there only because the Visual IDE wants them there.

So if a user is going to write a Visual application, then spend a week to a month optimizing the code so it''ll run good, why not just do it in Wordpad in the first place? The answer for MANY people that I have run across is that they don''t know a lot of the core functions, their arguments, and more. Like I said earlier, I admin three boards at "programmersheaven.com" and a lot of the time, the guys posting Visual questions have no clue about anything beyond the IDE, and when we mention function names, arguments, pointers, memory refereces, and the like, they reply with "huh?".

This isn''t to say there are a handful of true coders who use Visual to get rid of the tedious task of doing the same things over and over again, such as the WinMain() or CallBack functions. Then they do 90% of the actual coding themselves. These guys are fine with me. But the majority of Visual users don''t grasp anything beyond the IDE, and if shown even simple code, will be lost. I''ve been running those boards for a while now, and this is the case nine times out of ten. I didn''t mean to offend any of you, because I know there are good coders out there who simply sue Visual, but I am referring to the majority when I just open my mouth like before.

-The Great Sephiroth

Share this post


Link to post
Share on other sites
RonHiler    214
quote:
Original post by The Great Sephiroth
Sounds like you're a fan of the Visual tools

Yes and no. I'm a contract programmer, and when I want to quickly prototype a UI for a client, I use visual tools (Borland actually, since I consider the VCL much superior to the MFC for that purpose). Using this method, I can have a pretty functional UI up and running in less than a day, and the client gets a hands on demostration of where I'm going, and can request changes or modifications before I get into serious coding. However, when I get to the actual coding, I usually switch over to vanilla Win32 code, usually, because I prefer to have more control over the controls, so to speak

However, you seem to be failing to make an important distinction. Using an IDE != using VCL || MFC. My code, when written without the libraries, has no more code in it than I put (except for all the standard win libraries we all use). It is no different than using WinPad, except I have all the advantages of the IDE at my disposal, such as color coding the text, smart indents, code stepping, watch windows, class lists, etc, etc. Using WinPad is getting you no advantage, and is actually handicapping you because you are losing out on all sorts of great tools that are there to help you. IMO

But this is the one that got me:
quote:

I've toyed with C++, but it's useless if you already know C.


I so strongly disagree with that statement I can't even begin to go into it There are whole books written on this subject, and if I may suggest, perhaps you ought to look into them to discover why C++ is in fact a superior language to C. C is a fine language, but it can only take you so far. Eventually the complexity of the project will begin to demand OOP techniques, and for that you need C++. I found "C++ Effective Object-oriented Software Construction", by Kayshav Dattatri to be an excellent resource. It takes a while to make the shift from straight C to C++ (it's much the same process as the shift from procedural to event driven programming), but once you do it, you'll never go back, and you'll find you can develop much more complex programs without losing track of what you're doing so much

Anyway, I'm sorry, I don't want to get into a holy war and there are several subjects here that are very volitile and likely to go in that direction If it works for you, use it, far be it from me to act all superior or anything. I'm just suggesting you may want to examine a little closer why C++ and IDEs are so dominant in our industry. It's not an accident that so many smart programmers use these tools

So, to get back on topic and answer your questions (if they haven't already been), UDP packets are guaranteed not to split if they are less than 500 or so bytes (they're not supposed to split even if bigger than that, but my understanding is that some routers will do so). Also if a split UDP packet doesn't come through entirely (if part 2 of 3 was dropped for example) all 3 parts would be dropped (thus you effectively triple your chance of losing the packet).

So:
1) You don't have to worry about dealing with split UDP packets, you should never see them. IF you get them, they are supposed to be complete and in proper internal order.
2) If part of a split UDP gets dropped, the entire packet is silently dropped. For this reason, it is best to keep your UDP packets <= ~500 bytes.
3) Don't have to worry about this.
4) Bascially, yes. As Webby says, you cast into an pointer of chars to send. At the other end, you return them back into the original structure.

quote:

Even if some guy on a 14.4k modem sends a UDP packet that is say, "char Message[8192]", my "recv()" function on the server won't get the packet until it has been COMPLETELY reassembled by the system?


Right. However, it is *very* likely you won't get the packet at all, since it will split up into as many as 16 different packets, and if any one of them is not received, the entire lot will be dropped.

quote:

Is it possible that in a single "recv()" on the server, the server could get a whole packet from guy A and part or all of a packet from guy B?

2 billion, huh? That's a good trick You implied you are using non-blocking sockets(?). You won't get anywhere near that level with them. The IOCP model is your best bet for highly scalable servers. Anyway, to the question at hand, you won't get mixed packets. You won't get a packet complete notification until the entire packet is recieved. It is certainly possible to get packet parts 1-2 (of 3) from client A, then packet parts 2-4 (of 4) from client B, then packet part 3 from client A, then packet part 1 from client B in that order. However, they will (should) be reassembled properly before you get any notification (in this case, you'd get Client A's packet notification first, followed closely by B's).

Hope that helps.

-Ron

[edited by - RonHiler on September 1, 2003 1:01:40 PM]

Share this post


Link to post
Share on other sites
cbenoi1    484
> Sounds like you''re a fan of the Visual tools

I think you are talking about Microsoft''s integrated ''wizards'' and MFC/ATL; those generate source code from predefined templates, and modification to the source is controlled. The IDE concept -- the ability to do a complete edit-compile-debug cycle within the same interface -- has nothing to do with this; Sun and IBM have similar tools for their OSes. IDE and templated code generation are two different concepts.

-cb

Share this post


Link to post
Share on other sites
Thanks, Ron. I''m going to continue my model for the network code on both ends now. The server uses non-blocking but I have yet to make it work in Windoze. I''ll try the method somebody posted earlier in this thread.

And yeah, I shouldn''t have used "IDE" in my statements above. IDEs can be useful, but I have found that most IDEs can make code look funky. Borland is what I use also, and if I install the IDE and use tab instead of spaces of two, half of them come out as actual tabs and half come out as two spaces, so if the source is viewed in any other viewer, it''s mangled. The rest of the IDE is nice though, such as the debugger via menu stuff.

As for C++, I did a lot of research while toying with it. Everything I did in C++ I could turn around and do in C as well, so it didn''t seem worth the effort. My biggest argument on the entire C vs C++ subject is that C++ is converted to C before compiling, so if you already know C, why not just stick with it? Maybe you could explain that to me. I have several books on C++ here at the house, so I could pick it up easily enough, but it''s SO slow to code since just a simple struct (err, class) needs ten times as much code to make it work as it would in C. If you can tell me why it''s worth my time to go to C++ when all it does is get dumped back to what I code in now, I''ll probably make the switch.


-The Great Sephiroth

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
You are mistaken that C++ gets converted to C before being compiled. That was the original implementation of C++ and hasn''t been in use for some time (since the late 80''s I believe). While you are certainly correct that you CAN program in an object oriented manner and that you CAN do everything in C if you want to(Heck, this is what I do at my day job), it is best to be able to program in C++. This will help you find help when you need it, as evidenced by the fact that you could only find tutorials in C++. And also, you may understand why some problems are much better solved in C++. Unfortunately as you will soon discover standard asyncronous i/o for windows sockets is a serious pain in the ass. If you REALLY want asyncronous i/o, you probably want IO Completion Ports which are a rather interesting topic.

Share this post


Link to post
Share on other sites