 Hey everybody, it's Brian. I just want to give a couple quick updates and talk about a pet project of mine. This won't be a tutorial, but we will be talking about advanced, cute TCP servers. Highly scalable, if you will. For that, I want to wish everybody a happy 4th of July. Today's the 3rd of July and tomorrow we're going to go celebrate the 3rd of July in the parents of America and kind of to do an odd juxtaposition of that. I'm going to Europe in a little while here and I'm going to go to Paris. I'm going to go to London, Spain, and Italy. So we're going to actually spend a week in Paris and then we're going on a cruise. I think I'm only spending a day in London, but it's just kind of funny because everybody's like, oh, don't go to those foreign countries, especially France, because they're Native Americans. And I don't think that'll be the case, but we'll find out. I think a lot of people when they travel are just very ignorant of other cultures, but we'll find out. Also, we have broken the 5 million views and 30,000 subscribers. Now, I want to kind of point out we have a Voidrealms Facebook group and there's over 200 of us in there. So if you have a question, just remember you're competing with about 30,000 other people emailing me saying, hey, here's my source code. I need your help. My project's due tomorrow, et cetera, et cetera. It's actually very rare that you get my attention in my mailbox because I've got so many emails. And there have been times where I've had really great conversations and then I just lose track because they just get flooded. So anyways, onto the good stuff. One of my hobbies is working on TCP servers. If you go to my website, voidrealms.com, under tutorials, you'll see that we've done cute tutorials and you may have actually watched them where we've covered a basic TCP server using multiple threads, using a thread pool, using an asynchronous with a thread pool. And I've actually built an FTP server. I'm using cute and you can actually get the source code for that under source and then you filter cute and right there. The problem with these are, let me go back here, even when I did the advanced, you know, tutorial number 70, the advanced asynchronous TCP server with a Q thread pool, I found out that we're actually just doing the same darn thing. We're creating one socket per thread, which really is not the correct way of doing it. If you've done any research into the subject or if you've been working on this yourself, you realize that if you have a thousand connections, you'll need a thousand threads. Therefore, one thread per connection just will not work. And it's not really the way threads are designed to be used. A thread is a slice of time in the CPU that will get allocated for work. Think of it like an assembly line and in a factory of multiple assembly lines. So each assembly line is a thread. Each assembly line has different work packages on it that need to be completed in different stages of completion. That's a mouthful. Now think about that in terms of a server. All servers out there, while the high-end servers like Apache IS, etc., etc., they are multi-threaded at some point. But they don't run hundreds of thousands of threads, but they can handle hundreds of thousands of connections. That's not really true. I think Apache caps out around a hundred unless you tweak it and modify it. But it is doable. Somebody out there right now is screaming at their monitor going, No, my Apache server handles 10,000 connections. Yeah, but those aren't 10,000 connections pumping gigabytes worth of data. You just, it wouldn't work. So one of my hobbies is building highly scalable, blistering, fast TCP servers. And I've worked with a couple of people. One in particular, I think his name is Miguel. He got a firewall certification. He actually downloaded some of my source code and we kind of chatted back and forth. And I think he kind of came up with a solution on his own, but I always kind of felt bad because I didn't have a ready-made solution for him. So if you have done any research in this and you look for threading done right, you'll see, you know, there's huge discussions. I mean, there's 20,000 results out there of how to do threading in Qt. One of them, I haven't gone through them all, but one of them really stuck out. And it was Bradley T. Hughes and he says, you know, you're doing it wrong. And he is one of the developers out in the Qt channel on FreeNode. And basically, I'll summarize this. He says he gets a ton of questions on how to use Qt thread. And I think he actually helped build the Qt thread class. But people will inherit it like they do with Java and then override functions, which is just not the way it was meant to be used. To summarize this is you should use move to thread, but not move to thread this because then you're threading inside of your current object, which is not the way to do it. So point being a lot of the Qt TCP multi-threaded server designs you see out there are just dead wrong, mine included. And that's why I'm making this video is I've been kind of chipping away and working at this in my free time. And I get go when I say free time because I never have any, but let's go to this one first. This is a prime example of over engineering at its finest. Okay, I spent all this time and work and I made this really awesome TCP server that uses inline SSL and all this other stuff and I made these buffers like a line reader, a line writer, a file reader, a file writer. So you can actually send files and it won't take up the whole thing. You can set the connection speed. So if you want to send the file at 56k, it'll send it at 56k instead of taking the entire line. And I was really proud of my work. And then when I looked at the debugger, I realized that yeah, this is all the same design. It's not working the way it's supposed to, meaning it was one thread per socket. So I kind of scrapped all that, started over from scratch and said, look, I want a design that uses multiple threads that can handle multiple sockets per thread. That way it's done correctly. The way thread pools work is that the operating system will have a pool of threads. Yeah, no brainer there. But what Qt does under the hood is it looks at your CPUs, number of CPUs, virtual and physical, and the amount of RAM you have. And it says, hey, this is how many threads your computer could realistically handle. And then it throws those into the thread pool. So let's just do this. I'm going to run this little bad boy. You see, I have it set to two. We're going to run this. And I commented that out. So now you see, by default, Qthread pool gives me eight threads. I've got a pretty beefy computer here. I've got, I think it's quad core CPUs with, I think I've got 32 gigs of RAM. It's been a while since I've looked. You think I'd know. I built a darn thing. But anyway, so the principle behind the server here is that when it loads, it will start listening on one thread. And then it will make threads via the thread pool. And if you've worked with thread pool, you need a Q runnable object. The problem with the Q runnable object is it doesn't handle signals and slots, and you don't get any notification of when the work is completed. So we had those hurdles to kind of go over. The other hurdle was that I wanted this to be easily usable, meaning you could just download it and say, hey, I want to build something out of this. So kind of a proof of concept here. I did an echo server. Now, if you don't know what an echo server is, there are a couple school days where developers would shoot a packet out to an echo server, and the echo server would literally mirror that packet back untouched so they could see what they were sending across the wire. This was before they had protocol analyzers and all that fun stuff. So let's just, and we're not going to go through all these, but there's a server which inherits QTCP server. And we're overriding listen and close because we have to handle the internal thread pools. And let's just do... Yeah, so when we listen, we are starting the threads. And the threads is we just look at the thread pool max count, and then we just, voila, start each thread. Now, each thread can have multiple connections in it. So let's look at the TCP thread. And you'll notice there's an accept the socket descriptor and the owner. And there's also a move connection. That's really where the magic happens here. So when a connection request comes into the server, let me load this, it's going to go into the, you guessed it, incoming connection, which will then load up a, or actually it'll go out and find a thread in our pool that's free and available. And it will call the accept method on it. And then the connection actually handles the socket and the socket state, stuff like that. So we've got our Echo server in place here. And let's just look at that. So you can see our Echo server just inherits TCP server. And we're only, you know, overriding the start threads method. And when we look at start threads, you can see how we are making Echo threads instead of TCP threads. This is just basic inheritance. I'm just going through this so you understand what I'm going to show you here. And each Echo thread, it course inherits TCP thread. And when the accept is called, we are going to make an Echo connection. And that's what you would really determine with your protocol, whether you're going to do like an Echo or an FTP or an HTTP or whatever, is the actual connection class. The connection class holds all the, you guessed it, the socket and the connection information. So in the connection class, we're just overriding ready read. And we're just going to Echo the data out. That sounded complex. It's because, yes, it's actually pretty complex. It's taken me the better part of my morning to write this thing. So we're going to look at this. We're going to set it to two threads just because I want to, you know, not have to make nine connections to show you what this thing is doing. We're going to run this. All right. So we are listening on EA230. And that's the thread address. We're starting two threads. We're starting D0 and 30. Actually, we'll call it B30. And we're listening for incoming connections. So when we make a new connection here, let's just open and tell in that session. You'll see incoming connection. There's a socket descriptor on thread. So it's actually on our main thread here. The 12 EA230 is our main thread. We're accepting the connection on this other thread here. This 12 EEB 30. I wonder why I did that one. I should have done this one. Anyways, so that's now on a separate thread. We're going to open yet another one here. All right. So incoming connection. There's a socket descriptor on EA230. Yeah. And then accepted it on the other thread, this D0. So we've accepted. Where is it? Yeah. Accepted on EB30, this guy. And then accepted on DB0. So basically, two connections, one per thread. And this is where the design really deviates. We've got a maximum of two threads. So most TCP servers, they use the multi-threaded model. When you open your third connection or limit, we are beyond our limit, the connection is going to hang and not connect. What this will do is it accepts it. Remember, each thread can have multiple connections. And I haven't put a limit in there. So you could theoretically have 1,000 connections per thread. But obviously, if somebody is transferring a large file, all the sockets on that are going to have to wait for their time slice in the thread itself. So this guy, where was it here? Yeah. This one got accepted on EEB30. We're going to actually make a fourth one here. Just to show that we can do this. And accepted this one on EFBD0. So both of our threads, if we scroll up here, both of these threads now have two connections on them. So when I start typing in one and I send, you can see how there's bytes written. And it's echoing it back. See, echo client sent. And then we're echoing it back here. This guy right here is sharing CPU usage with this guy right here. Because they're on the same thread, where this guy and this guy are on different threads altogether, if that makes sense. So that is what I believe to be. Let me close this so you can see how it's actually going to clean up after itself. See, we get notification. Invalid socket, read disabling. Close that, yeah. So I still got a couple little bugs. But this is what I believe to be one of the better designs. You have multiple threads. Each thread can have multiple sockets. From there, you'll have to use locks and things of that nature to determine what resources can be used and limit the amount of bandwidth that you use per socket. That way, if Bob sends a file and there's five other sockets on that thread, it doesn't deadlock all those other sockets while they're sitting there waiting to send, because Bob's, you know, being a goofball. So anyways, let me know what you think of this design. I may actually throw it up on my website. I'm not sure yet, but just curious what you guys think.