 Hey everybody, it's Brian and welcome to the 69th Qt tutorial with C++ and GUI programming. And today we are going to do something a little bit different. I know I probably say that a lot lately, but socket programming is a little bit different. We're going to make a TCP server that uses a thread pull and I might have to explain what this is as we go. If you don't know what a thread pull is, you should probably take a moment to really research it before you get too deep into this, but I will cover it. So as you see, we're just making a project. Help if I could spell. Adding the network module to our project. One thing I really want to go over is what is everything that we've been doing so far. We've been making TCP servers using the Qtcp server class, which is very, very good. And it's very easy to work with. And we have actually made a multi-threaded server. The problem with multi-threads is, A, they're not really needed because Qt socket programming is a synchronous. We'll cover that in another tutorial, probably the next one. But also, when you make a thread per socket, you run a very high risk of crashing your server. The reason for that is every new connection makes a new thread. That's very bad because threads are very expensive. So we have the Qt thread pull, as it's called. Now, if you have no idea what a thread or a thread pool is, please go watch my previous tutorials where we cover multi-threading. But for this tutorial, what a thread pool is, is you have a collection of threads. And the Q thread pool manages those threads, so you don't have to manage them. And you can define an upper limit. You can say the max thread count will say five. So if you want to use more than five threads, it'll actually just put all your actions in a queue. And then once a thread is released, it'll recycle that thread and reuse it. That way, you're only at most using X number of threads. You're not creating one per socket. And you'll see what we're talking about here in just a minute. All right, so first things first, we need to create a couple classes here. So we're going to add new, we're going to add a class, call this myServer. And the base class for this is going to be, you guessed it, QTCPServer. So the first thing we need to do is remember how to spell that correctly. Because remember, this is case sensitive here. And I think it's Q uppercase, yep, TCPServer. And here it's QObject, hit Next. And if ever you've created a class and you don't know if you just did it right, wait for it to scan your project. Give it a quick build. And I said quick build, there we go. And it builds successfully, so you spelled it right. So this is our server. And we're just going to flesh this out really, really quick here. We want a public void, call this startServer. This is where we're just going to start server up. You know, you've seen this half a dozen times so far. And then we're just going to go incoming connection with the socket descriptor. Notice how they call it a handle, same thing. And then for our private object here, we're going to have a Q, can't do that yet, sorry. We didn't include it. So let's just go ahead and back up here. I'm going a little too fast, Q thread pull. I'm actually pretty excited about this tutorial. So let's add our includes. Shame on me for not doing that earlier. Now we will go ahead and throw in our private Q thread pull. The reason why I'm excited about this tutorial is because a lot of times you'll get the basic how to make a TCP server, but nobody ever tells you how to do it correctly. It's not until you've made one, it's gone into production, got 2,000 connections and just exploded that you learn from your mistakes. So I'm trying because I've done this before, well I'm trying to really get you from making the same mistakes that I have made. So let's go ahead and implement our server here. Add in my server. You guessed it, start server and then we'll say avoid coming connection and that's where we're going to handle our incoming connection request. And then this is the typical, you know, if this listen, Q host address and we're just going to say any. You know what that means. One, two, three, four for the port and we're just going to have some basic debugging going on here. Cue to bug, we're just going to say, yep, server started, trying to go through this part really quickly because this is all review for you by now. I mean you can probably do this blindfolded, server did not start. Now the meat and potatoes, if you will, of this code is going to happen right here in the incoming connection. What we need to do is we need to add something to our thread pool, which we haven't created yet. So let's go ahead and do that. And if you've really gone through the Qt documentation, you know that there is a global thread pool that's assigned to every Qt application, but just for the sake of demonstration, I'm going to make a new one just to show you how it works. And with this, we're going to say pool, set max, connect max thread count and we're going to say we want a maximum of five threads. So at any given time, this is only going to use five threads. If we get 5,000 connections, it's only going to do five threads. Those other 4,995 connections are going to sit in a Qt state until a thread is released and then it'll do what it needs to do. Now in order to work with this, we're going to have to go pool and we're going to have to, oops, sorry about that, lost my mouse, we're going to have to start an object. Now notice how it says Q runnable. That's probably something we haven't really discussed a whole lot. What is a Q runnable? A Q runnable is just a task, a piece of code that you want to execute. And we need to create one of those. So let's just comment that out for now. I'm going to make a new class and we'll call it my runnable. That's actually a horrible name. It makes it sound like I have some sort of funky disease or something. That is kind of not sure if I want to name it that or not. Let me think about that for a minute. That's kind of a gross name, but you know, we'll just stick with it Q runnable heart. Now try to compile this and if you're like me, you'll get a successful build. Now if you try to do anything other than this, my runnable public Q runnable, like if you've got the object parent, blah, blah, blah, it won't compile. Why? Because Q runnable is not technically an object. I shouldn't say it's not a Q object. It's something totally funky. I don't remember exactly what it is. Anyways, point being we need to include some things here. So we're going to include QTCP socket. And of course our handy include Q debug, which a couple of you pointed out, Brian, that's already included. You don't need to include it, but I like to do it just so people who are fairly new can figure out what in the heck I'm doing here. So one thing we need to do is say int socket descriptor. That way we can get the socket descriptor. Now note that normally in production code you wouldn't do that. You do it as a private variable and you do getters and setters to get and set the variable. But you know, this is tutorial so we're just going to go through this fairly quickly. And then of course we want protected, avoid, run. Now you notice how this is similar to how a thread is. You have a run and you call it by start, but this is not a thread. Repeat after me. Q runnable is not a thread. One more time. Q runnable is not a thread. There's a very big difference between these two. Q runnable is a task that is executed on a thread in the thread pool. So it is not a thread. It's just a task that we're doing. Alright, now we can go ahead and implement this. And we'll say avoid my runnable run. And this is where our execution is going to start here. And we'll say if not socket descriptor then return. Just in case we don't have a socket descriptor we just want to branch out of there. Q TCP socket. We'll just say socket and socket set descriptor. Set socket descriptor, that's what it is. Actually we don't want this. Get our socket descriptor that we said earlier. Now that we have an active socket we can just, you know, I mean whatever we want to do here. We'll say right, we'll just say hello world and socket. We want to flush the data and then of course we will just do socket wait for bytes written. Now, after we're done we just want to do socket.close. That way we free this up and this thread that's running this task can be reused for another one. Very, very simple example here. Now we need to go back into our server. And we need to actually create an instance of this. But before we do, sorry, we got to include it. My runnable, I cannot get over that name. I should have chose a better name. My runnable. It sounds like you had some pretty bad Mexican food or something and you're doing a runnable over to the bathroom or something. And I know, I know, bad bathroom humor. My runnable. Notice how it's a pointer too. And we'll call it task because I don't want to call it my runner because that just sounds gross. New my runnable. Now one thing you should note is the task set auto delete. We're going to set this to true. And what'll happen is Qt will automatically delete that object so we don't have to do anything with it. But we could set that default and then after it's run, do some gobbly cook with it and set up signals and slots so we can tell when it started and stopped and all that stuff. Then we're just going to say, of course, task soccer descriptor equal handle. That way it has something to grab onto and we're going to say pool start. And then we're just going to say task. Notice how you can also set the priority. We're not going to really worry about that just yet. Let's go ahead and fire this up, see what happens. Actually, nothing will happen because we haven't set the code to start it. Sorry about that. I mean, it's such a rush to show you guys this that I'm kind of doing a horrible job here. OK, include my server. Oops, not my runnable. I cannot get over that name my runnable. I know I'm going to get some fan mail about that. OK. My server. I'll just call it server, start server. Now let's go ahead and fire this up. Server started on port 1234. I'll just start a command prompt here. And hello world. Now what you should know is what happened. In the background, the QTCP host got a new connection request. It made a new my runnable or a queue runnable object. And it threw it into the thread pool. One of our five threads grabbed that task and ran it. If you had 5,000 other people hitting at the same time, those 4,995 would just be sitting in an idle state until the rest of these are processed. That's a very good way of handling this. It's very smooth. It's very scalable. And it will not kill your server. Basically, you can get hundreds and thousands of connections, and it'll just go through them as it gets them using the threads that you define in the max thread count. So that's really all for this tutorial. I know it's so deceptively simple that it's hard to wrap your head around the first couple of times. But really, all you need to know is, during your incoming connection, you're making a new runnable, you're setting the auto delete to make sure you don't clog up your memory. Setting the socket descriptor and then saying, our thread pool, start the task. And then when you actually have your task, you do your block of code. And you could create objects and do anything, but you should note that while the execution contact is in this run, it's going to be holding that thread and locking it so that you can't really do anything else with that thread. So no one else will touch it. So that's all. Appreciate your comments and feedback. Keep it up. I know I've been not as fast with the videos as I want. TCP programming's a little bit complex, and I want to make sure I get these done right the first time. I had a couple of videos that I actually didn't like, and I deleted them and re-uploaded them. Anyways, keep up with the feedback. You guys are helping me learn along with you guys learning. Talk to you later. Bye.