Game Programming S2 E05 - Connecting the Client and Server
The Cherno
·
Intermediate
·9y ago
Key Takeaways
The video demonstrates the connection between a client and server in a game programming context using UDP and socket programming, with the client and server being separate applications. The client resides in the game package, while the server is standalone, and they communicate using sockets.
Full Transcript
[Music] hey what's up guys My Name Is AO and welcome to episode five of the game programming series season 2 so we're back unfortunately I didn't have time last week to make an episode but we're hopefully back to more or less a weekly kind of uh schedule here and Last Time episode 4 we talked about uh really how the server would receive packets and this whole listening process and the whole processing kind of process and I even gave some examples in terms of the RC database and we would actually handle something like you know a login request or something like that right so what we're going to do today is actually start setting up the client side because whilst we have a lot of kind of server stuff going on here I mean we don't have like a lot or anything but we do have like quite a quite a decent kind of start foundation for our server unless we set up a client right now there's no way to test any of this I mean I've told you guys that you know we have this listen thing that will theoretically accept packets and we have a a me here called send which will send packets all of that stuff is all good but we can't test it because we need you know in order to test networking you need to have two things right if you have you're all if you're all alone then you can't really test out your your your multiplayer capabilities so what we're going to do is we're going to create a friend for ourselves uh known as the client uh so that we can talk to the client uh and socialize and uh and hopefully transmit data back and forth so to do that that I mean because we we kind of have in terms of our project set up we have this rain project of course which is our actual game that's the one that we kind of care about that's where the client is going to reside um the the server of course is a standalone application that runs on an actual server right so it it would run on a dedicated computer or like it I mean it doesn't have to run on a dedicated computer I mean obviously you could just run it on your same computer that you were playing the game from and that's fine um but what I mean is it is actually like a standalone application that runs on its own right it's not part of the game or anything like that however the client of course needs to be part of the game because like the game is the client so in in this rain kind of package uh we have this pack we have another package called net which is kind of where I set everything up and that's where we're going to kind of uh create a new class inside the net package um and I mean I'll probably just end up calling this client uh we called the server server so it kind of makes sense to call the client client um I am going to quickly look at server and see what we've got here because I mean theoretically we kind of will be uh taking a lot of what we have here um and putting it into our client I mean not like in a huge kind of way where we kind of just change absolutely everything as in like there will be changes that we need to implement obviously like for example here we just start a diagram socket with a port and everything um oh actually one thing I should mention and I did mention this last time is that because this is UDP there isn't like this initial kind of you know connection being established right there's you know like TCP has that whole three-way handshake kind of thing that I'm not going to talk about um UDP doesn't have anything like that because again going back to my incredibly awesome mail analogy all that UDP is about right is it's like it's like kind of you know you you have this mailbox set up and you kind of go there and you collect mail uh or you put mail in there and then the postman comes and takes it right it's that kind of thing where it's just kind of there's no guarantee of really anything you just kind of you have a drop off location it's almost like some like Ultra kind of shady deal going on where you where you get told to drop off your thing or whatever it is at a particular location and and then someone might take it someone might not take it but you drop it off and you leave and that's it and then you receive further instructions right it's kind of like that um yeah that brings back memories anyway sorry back to this um so basically uh in order to set this up I mean all it's going to be really is again real simple kind of the same thing as a server in terms of we establish a socket which is like our mailbox our um our mailbox yeah um and then we uh of course can kind of send and receive packets so let's do it um when we set up a client we're going to set up a Constructor of course which takes in a port um we'll assign a port to a field just like we normally kind of do um what else do we have in our server that's really all we did and then we have this this start thing which kind of you know did stuff so uh where this is where the differences are going to come because we're actually going to write a function called connect right and not only are we going to write a function called connect we're actually also going to write an address into our um into our client here now the reason I'm doing this um is not keep in mind because suddenly there is going to be like an official kind of connection thing that we run no the actual low-level kind of API in terms of the parts of Java's API that we use for this are indeed going to be identical to the server it's just that we're kind of simulating like our we we're creating our own kind of connection situation right because of course we do kind of theoretically from a high level we do need to establish a connection even if the low like if the low level doesn't support that we'll have to add on that functionality because you know from an abstract kind of high level point of view we require it excuse me so let's do that um the other thing I'll quickly do by the way because this is going to get a bit annoying um is uh so we'll St the inet address I think I believe we I mean the server wouldn't have had an address no it wouldn't have um and then when we when we did do s we we took in the inet address thing so I guess we'll do that and then that means that of course when we assign address we'll have to do inet address. getet uh get by name right and then the host of course is the address okay um this will kind of be I might actually call this the server or the host or something because this is kind of the host like address right um and of course that will kind of throw an exception so we'll we'll handle that and of course we'll we'll um I'm not even sure if we maybe should do that here it might be worth doing it when we actually decide to connect um because of course that means they establishing a connection yeah okay we're actually going to move this down so we will still store string as we'll say IP address uh and Port okay and then we'll just say uh this do IP address not that we need the this in this case but anyway this IP address equals host and this port equals port and then of course when we do here that's where we'll actually attempt to establish that thing so the reason I've done that is because I don't want the Constructor of client to start throwing all these exceptions and everything right it shouldn't be doing that connect is when we actually do stuff by constructing a client all you are doing and all you should be doing is basically setting up your data right you you're setting up your parameters that's it you're not actually doing anything like validating the IP address which is what we're about to do here right so I kind of want to ensure that I'm maintaining some kind of level of uh of order around here so we'll say I Pi um we'll say uh okay so we will need an actual inet address I'll call it server address probably um so server address equals oh what do we have there yep server address equals inet address. getet by name and then our host of course is this IP address that's going to throw an exception but no worries we'll surround that with a try and cach and handle that so of course um I'm going to be really simple with this I'm going to return a bulling if there is a problem we're going to uh basically return false if you wanted to you can maintain some kind of error code um I guess I should probably because we're trying to be good programmers here um I mean just to show you guys something that you could set up that's kind of really easy is we could have uh an enum called error or something right and then we're going to have like you know none and you could theoretically return this instead of a bullying but I kind of like returning a bullying instead um it doesn't really matter um so we'll have none we'll have like invalid host um uh we'll have uh so invalid host uh let's see um I'm trying to think of a good way to describe uh the lack of a connection [Music] um invalid host okay we'll come to it I don't know [Music] um uh yeah I don't know I don't know invalid connection seems like a weird term I'll probably think of something as I continue but basically if this happens of course I don't know why I did that I meant to do this of course we'll print stack Trace kind of on debug builds I guess um and then we'll also what we'll do is we'll have a private error error code or something which will be equal to error. none by default of course and then I guess we'll set the error code for example here to invalid host okay um so this is one way of doing it you could you could obviously also make it so that you return an error and then you could check to see if error doesn't equal error like if error uh doesn't equal error. none it means you've got an error okay so that's another thing you could do um up to you I'm just showing you guys kind of different ways to think about this uh okay so we've got this Ser address set up we'll do the thing that we always do which is um which is set up the uh what's it called our um datagram socket so we have our socket I keep commenting stuff uh so we have our socket of course which will be a new datagram socket um of course we're going to set that up on our Port um and this will throw its own kind of socket exception so this again is maybe uh something you might want to handle I don't know I'll keep this simple for now and man I got to stop doing that how do I keep doing that control control forlash it seems um so AR equals socket exception return false uh error code and of course we'll have something by the way that's obviously like get error code or something which returns that error code maybe also we have something that just automatically prints it as well or logs it to a file lots of things we could do right um so assuming our soet is set up we're basically ready to go um so we're going to move on to kind of sending uh stuff so if we have a public void send uh again this is a different situation than the server in the server our send method required an address because we need to know where we're sending it to this is the client the only the only thing the client can connect to is a server right the client should only be sending data towards the server now you might have multiple servers you might have multiple places that you theoretically want to send information like for example maybe you have maybe this is like a multiplayer game obviously and so you have your server where you send your like positional information and actual gameplay related stuff but then you might also have like another server or another set of data that you want to send basically which is telemetry data so for example metrics and like stuff like that right just for like statistics purposes and just you know whatever um so Telemetry you might want to send obviously to one server and then actual gameplay stuff you might want to send to another server so yes you could have multiple servers that being said um we're going to assume for now that the server you're going to send to is just that one okay that's the one that you specify when you make the client and that's it maybe of course if you wanted to send to multiple servers or you wanted to you know I guess connect to two different servers again one for maybe like for different purposes you could just create two instances two instances of this client class and theoretically that should work okay so now that's out of the way uh because of that all you really do need to send is that bite uh data right that we have like this stuff is not required so we have data uh to save a bit of time I'm just going to grab this and copy it and paste it into here because it's going to be identical the address of course is going to be the host address or the server address I called it um and What's your deal there you good now okay there was a warning saying that was unused but of course it is it is used now uh this is yep okay so we have this uh and then the port of course that we're going to send to will actually not be um uh this um oh yeah this is interesting sorry this is where I need to actually mention something CU I've done this wrong um this port is not the port of the client right this port is the service port and in fact to clear that up I'm actually going to create another Constructor that will just be like string host which won't container port and what this will do is basically uh format will be something like 192.168.1.1 column like 5,000 or something right where you basically have this colon here and you have the whole IP address here because that's kind of how you want to provide it um this will basically just be like uh your format where you have and maybe I'll stick this like here or something just so that we know there we go that is for that um and then the format for this will be uh might just write example instead um and then the format here will be basically you know that and that so we're kind of we've kind of separated it right that's kind of how we're going to roll um so we'll shut that down for a bit um and so what then what we'll do here as a really simple thing of course and we can you know put inv valid host if it fails maybe uh is we're going to just basically grab the host um we're going to split it by a uh colon right um which will give us two values now that will basically be uh I don't know Parts um so we split that by that of course um we can probably do some other kind of stuff to verify that it's correct for example if parts do length doesn't equal two then we know there's an issue so we can probably uh do two things we can set the error code to invalid host so we are doing some kind of validation here by the way it's just that we're not doing actual like validation in terms of that we're just doing very basic string validation um and return okay that's one verification we can run of course the other one is going to be we're going to set the IP address to uh Parts zero and then we're going to set the port to integer pass in Parts one now if this fails which we're going to verify so if that uh throws a number format exception we're going to return and we're going to set the error code again to invalid host all right so we should now have the port and the thing uh the port and the uh IP address just from one string this time so we don't have to provide that and of course we'll test that stuff how we going for time 16ish minutes okay it's not the worst thing in the world excuse me okay let's uh let's let's accelerate this a little bit so um we have the socket of course uh so what I'll do now is um yes so that that's that's kind of where I left off this port is the port of this isn't correct what we actually want to do is create a socket with just that right I mean of course we could specify some other Port it's definitely not going to be this port I mean it could be theoretically but it doesn't it could be like a random Port it doesn't matter obviously like within the correct range um so it could be like that or something that's fine uh if but the the point is we don't care what port it is because this is the client okay we just need some kind of unused Port so that we can essentially again we just want to set up a mailbox and then that that way we can send data to the server since no one's going to be connecting to us right since no one is going to be sending us Data before we send to them we don't need to basically publicly set our port or IP address for that matter right all you need to know is the IP address of the server when the server receives your mail right there will be a return address on your letter which means that the server will be like okay I can see where this mail came from I'll return it you know back or I'll send my new letter back right so analogy aside when we when the server receives a packet from the client the packet will have the IP add address and the port from which that packet came from so then when the server wants to send the client a packet the server can do so by sending it to the basically to the address and Port that it retrieved from the packet that it received from the client okay it's kind of complicated but it's really really simple don't overthink it too much so that being said um that's kind of how that that works so because of that we can just say new datagram socket that'll give us a random Port because we we don't really care okay all we like the only reason we need these two or the only reason we need the server address and the sorry the only reason we need the IP address and the port which is in other words the server address is because we actually want to um or the server address and the port Y is because we actually want to Connected the server okay that's it so we haven't done any connecting yet we've just created a mailbox or a socket um ideally now what we want to do is actually try and send the data so again we try and send it to the server address in the port doesn't work out we won't really know um which is why we kind of need that acknowledgement so uh what we'll do here is we will attempt to basically send a connection packet okay which will be private void send connection packet now this is going to format some kind of packet I'm going to be really simple with this I'm just going to say we have our data which is going to be as simple as um for now maybe we'll send connection packet again obviously that's a huge waste of like bandwidth and everything because it's huge we could probably send something like some kind of code or something like really simple and probably not a string but anyway this will be as good as we really need to be for now um as in this is a good test and of course we'll send that data and it knows exactly where to send it to now assuming we get that successfully which we probably will um we should do two things first of all we definitely need to make sure that we're sending this on a different thread but we'll talk about that next time um and the other thing will be uh we need to um obviously like hopefully receive something but we don't really care about that right now um and then we'll return true if that's successful again we don't know if it's successful yet but what we're going to do here is wait for server to reply which again we'll talk about next time however we've done all this work so let's at least test it out and the way we're going to test it out is by are doing two things first of all back in my game I believe I left a two do saying connect a server here so let's try that out we'll say client client again we'll just do this all sandbox in here for now client client equals new client uh we'll try the normal way first so I'll still do Local Host however the port I believe was was like 8192 because that is my favorite Port of all time for some reason yep so the port that the server is running on is 8192 by reading the rain server class um so we'll sck that in first 8192 okay and then of course we'll do client. connect okay so how are we going to know if this connect well first of all we're going to run this and we're going to see if we get any exceptions now we shouldn't get anything at all but let's just see what happens okay game runs normally nothing complains fantastic now let's start the server and specifically I believe we might have no no we didn't okay so what we'll do now is in the process method for now um here's what we're going to do so we have the data this is back in the server class of course right server class um we have our process uh datagram packet uh we're going to ignore the rest of this stuff so a good way to easily ignore it is just say if true return uh if you just write return Java will not let you compile that code for some reason so you have to write if true return and that's basically just the same as commenting out the rest of this code it's just a bit easier um because we don't actually want to process this yet so we have the data the other thing I'll get though is the address which is going to be packet. getet address and then finally the port we also want to know the port of where it came from packet. getet Port okay so that's what I meant by when you send a letter you have your return address on it right packets also have that packets have the actual data which is the contents and then they also have where they came from that's very important because of course we did start our client on a random Port so even if we somehow know the IP address of the client we don't know the port okay there's no way to know I mean uh not that you would in a real world scenario you wouldn't know the IP address of your clients anyway right as in like before they connect you have no idea who's going to connect right when they connect you can see what IP address connected thus you have their IP address and Port so that you can send them back data but um obviously you're not going to know like in this case we know that the IP address of the client is going to be Local Host because I'm running it on the same thing but of course in a real world scenario you wouldn't know so it's obviously vital for the packets to contain that information and for us to have it so what we'll do is easily what we'll just as a debugging thing we'll we'll kind of do a print packet thing or I'll just do dump packet okay and what dump packet will do is it will basically uh take in I mean I guess we can just take in the packet this is what we need from it though okay so I'll quickly copy that and write a method here probably I'll do it at the end so we'll have like all our debug Methods at the end private void dump packet and we'll have whoops a datagram packet that's a socket okay these are all the that's basically the information I want to dump um and then we'll basically just say uh maybe something like packet and then we'll have an IP address and a port so the way we'll do this is I'll just do a little tab here so that it shifts along and it looks nice um I might even cuz I'm like being fancy I might even do something like that uh at the beginning and at the end cuz you know printing is fun um we'll do uh plus address uh. get uh is there a good kind of get host name get host address this is the IP address in the string format that's kind of what I want plus and then we'll do the port okay so we have that set up um and then of course we might as well kind of print the the data um an easy way to do this probably I mean we we know that we received a string so we could easily just do something like um I'll do this uh so contents [Music] um and I might do just an extra print line here okay Eclipse just null pointer exceptions itself that's fun um anyway hopefully that wasn't like too bad um then of course for the contents for example we can do and maybe I might do even two tabs here uh I'll just for now I'll grab that bite array and I'll convert it into a string okay and then hopefully like that will be kind of okay I mean in this case it will be but of course in other Cas is when we send raw data which will have like you know zeros in it n termination characters this is not a good way to print you know bites of data but in this case it'll be fine so we're dumping our packet and that is good and then of course we will'll need this because we need to like when we take in the process we want to know which client it came from so that of course we can tell all the other clients connected for example which player has moved where okay important stuff um okay un 26 minutes wasn't it 16 minutes like a second ago oh my making these videos between 10 to 20 minutes long is absolutely impossible I should stop wasting time sorry um this is the worst okay sorry anyway back to this um where were we uh yes so uh receiving okay so hopefully now if we start the server which I'm going to do by just being like you know debug as Java application I guess and hopefully that means the server started we're not even printing anything but hopefully the server is listening um what I'm going to do now is I'm going to start the client and then hopefully the server should print that you know connection packet text that we sent so um uh what am I looking for debug as Java application and okay let's maybe okay let's just close the client now in the debug tab I want to switch over to the server which is still running and then hopefully awesome what you can see in the console in for the server as you can see this is the server's console it says packet from this IP address and this port so that is a local host IP address of course that is a random Port that is that it it has assigned and the contents of this packet are connection packet which is exactly what we sent fantastic okay there we go so you can see how that's working now we're now sending information and this will theoretically as long as like it's allowed through firewall and everything work all around the world right as in if I had another computer somewhere in on my local network or on an external network and whatever it would theoretically work as long as I started my server on that and the server was allowed through firewall and it was like the ports were forwarded correctly on your router and everything theoretically if you did that and then you from another computer somewhere in the world tried to connect to that IP address and that port then you would be able to send data to it okay so that is now working um and uh that that is a good place to wrap up the episode so thanks for watching guys hope you enjoy this video if you did please hit the like button leave any questions you may have in the comment section below I'll try and write them down and answer them in the next video or just reply to them via YouTube uh if you want to support the series and get the source code all of the source code is available on this game programming repository which is a private GitHub repository with every um with every episode as you can see as like a separate commit so you can see like exactly what has changed since the last episode and all that stuff if you want access to this all you have to do is support me on patreon if you pledge $5 or more per month which is like I mean what that's like a cup of coffee or two right I mean not a big deal if you pledge that you receive you receive all this code uh for the game programming Series so that you can so that you can make sure that you're writing the the correct code and of course by doing so not only do you receive the code you also me meaning I can continue making these videos so anyway thanks for watching guys hope you enjoyed this video and I'll see you guys next week with another game programming episode goodbye Voom
Original Description
Source Code ► https://www.patreon.com/thecherno
Follow me on Instagram! ► http://instagram.com/thecherno
Twitter ► http://www.twitter.com/thecherno
Slack ► http://www.slack.thecherno.com
Stream ► http://www.twitch.tv/thecherno
Website ► http://www.thecherno.com
Facebook ► http://www.facebook.com/thecherno
Want more? You can help out by supporting me on Patreon! https://www.patreon.com/thecherno
-------------------------------------------------------------------------------------------------
Website: http://www.thecherno.com
Twitter: http://www.twitter.com/thecherno
Facebook: http://www.facebook.com/thecherno
Subreddit: http://www.reddit.com/r/thecherno/
Steam Group: http://www.steamcommunity.com/groups/thecherno
-------------------------------------------------------------------------------------------------
Outro music is by Approaching Nirvana: http://www.youtube.com/approachingnirvana
Watch on YouTube ↗
(saves to browser)
Sign in to unlock AI tutor explanation · ⚡30
Playlist
Uploads from The Cherno · The Cherno · 0 of 60
← Previous
Next →
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
3D Game Programming - Episode 1 - Window
The Cherno
3D Game Programming - Episode 2 - Game Loop
The Cherno
3D Game Programming - Episode 3 - Arrays
The Cherno
3D Game Programming - Episode 4 - Drawing Pixels!
The Cherno
3D Game Programming - Episode 4.5 - How Rendering Works
The Cherno
3D Game Programming - Episode 5 - Playing with Pixels!
The Cherno
3D Game Programming - Episode 6 - Performance Boosting
The Cherno
3D Game Programming - Episode 7 - FPS Counter
The Cherno
3D Game Programming - Episode 8 - Alpha Support and More
The Cherno
3D Game Programming - Episode 9 - Beginning 3D
The Cherno
3D Game Programming - Episode 10 - Floors and Animation
The Cherno
3D Game Programming - Episode 11 - Rotation
The Cherno
3D Game Programming - Episode 12 - User Input
The Cherno
3D Game Programming - Episode 13 - Render Distance Limiter!
The Cherno
3D Game Programming - Episode 14 - Basic Mouse Movement
The Cherno
3D Game Programming - Episode 15 - Textures + More!
The Cherno
3D Game Programming - Episode 16 - Walking, Crouching, Sprinting + More
The Cherno
3D Game Programming - Episode 16.5 - Exporting Runnable Jars
The Cherno
3D Game Programming - Episode 17 - Small Adjustments + Birthday!
The Cherno
3D Game Programming - Episode 17.5 - Creating an Applet
The Cherno
3D Game Programming - Episode 18 - The Beginning of Walls
The Cherno
3D Game Programming - Episode 18.1 - A Few More Things
The Cherno
Episode 18.5 - Creating an EXE File in Java
The Cherno
3D Game Programming - Episode 19 - Rendering Walls
The Cherno
3D Game Programming - Episode 20 - Continuing Walls, Fixing Bugs, and Managing Crashes
The Cherno
3D Game Programming - Episode 21 - Texturing Walls, Fixing Clipping, and Fixing the Mouse
The Cherno
3D Game Programming - Episode 22 - Random Level Generator + Properly Fixing Clipping
The Cherno
3D Game Programming - Episode 23 - Graphical User Interface (GUI) Launcher
The Cherno
3D Game Programming - Episode 24 - Making Our Launcher Work
The Cherno
3D Game Programming - Episode 25 - Writing and Reading Files
The Cherno
3D Game Programming - Episode 26 - Custom Resolutions
The Cherno
3D Game Programming - Episode 27 - Decorating the Launcher
The Cherno
3D Game Programming - Episode 28 - Continuing our Custom Launcher!
The Cherno
3D Game Programming - Episode 29 - Launching The Game
The Cherno
3D Game Programming - Episode 30 - Colour Processing In-Depth
The Cherno
3D Game Programming - Episode 31 - Sprites!
The Cherno
3D Game Programming - Episode 32 - Sprite Mapping
The Cherno
3D Game Programming - Episode 33 - High Resolution Rendering
The Cherno
3D Game Programming - Episode 34 - Entities
The Cherno
Genesis - My Game for Ludum Dare 24
The Cherno
Vlog + Ludum Dare Results
The Cherno
Game Programming - Episode 1 - Resolution
The Cherno
Game Programming - Episode 2 - Threads
The Cherno
Game Programming - Episode 3 - Game Loop
The Cherno
Game Programming - Episode 4 - Window
The Cherno
Episode 5 - Buffer Strategy
The Cherno
Game Programming - Episode 6 - Graphics Initialized
The Cherno
Game Programming - Episode 7 - Buffered Image and Rasters
The Cherno
Game Programming - Episode 8 - The Screen Class
The Cherno
Game Programming - Episode 9 - Rendering Pixels
The Cherno
Game Programming - Episode 10 - Clearing the Screen
The Cherno
Game Programming - Episode 11 - "Out of Bounds, Baby!"
The Cherno
Game Programming - Episode 12 - Negative Bounds
The Cherno
Game Programming - Episode 13 - Timer
The Cherno
Game Programming - Episode 14 - FPS Counter
The Cherno
Episode 15 - Tiles
The Cherno
Game Programming - Episode 16 - The Map
The Cherno
The Walls 2 - Minecraft PvP Survival Map
The Cherno
Game Programming - Episode 17 - Key Input
The Cherno
Game Programming - Episode 18 - Controlling The Map
The Cherno
More on: Distributed Systems
View skill →
🎓
Tutor Explanation
DeepCamp AI