 Welcome back everyone. This is Brian. And in this video, we're going to discuss blocking versus non-blocking sockets. I'm going to paste some documentation here. So blocking stops. Whenever you see the word blocking, think immediately like you're going to shut the door. So blocking will stop execution of your program, and then it will proceed once the function completes. Non-blocking, which is a little bit new to us, this is what we're going to cover in this video, runs in the background. And there's really one correct way of doing this, and that's to use select. This is completely new to us, and it looks horrible, so I wanted to explain it right up front. What we're going to do, we're going to hand it a list of readers, writers and potential errors, and give it a timeout. Very important you give it a timeout, otherwise it will actually block, which defeats the whole point of non-blocking. It in turn is going to give us a list of things to read, things to write, and errors. A little bit crazy the way this works, and to be brutally honest, this gets super complex. So we're not going to do it the ultra professional way. We're dialing it down and doing it the newbie friendly way. And spoiler alert, yes, there are whole frameworks on how to do non-blocking programming. We're not going to cover those just yet. We're still in newbie land. We will get there eventually. So if you want to go out and peek at this documentation, you can see it's kind of complex. So we're going to try and dial it down. The basics here is in Python use a socket set blocking zero to make it non-blocking. That's the big takeaway here. But the moment you do this, bad things happen very quickly. And the author goes on to say, the correct way to do this is use select. And then they give you the template, which I just displayed. Let's dive in and take a look. As you might expect, the first step in any program is well imports. And I'm going to save just a microsecond of time by doing the old copy and paste. We're going to import logging, socket and select. Now, you notice if I hover or select it says this module supports asynchronous IO on multiple file descriptors. What? What does that really mean? So we're working with asynchronous programming. We covered that a little bit in this series so far. And we're doing that on multiple file descriptors. Now that really in plain English means we're going to do something on the same thread at the same time using a file descriptor. Now a file descriptor, this is a little complex, but basically on Unix, everything's a file descriptor. It just means it's a hardware device of some kind. It gets more complex, but that's the dumbed down version of it. On Windows, only sockets are supported. Very, very, very key takeaway on this. So if you try to use the select with a file on Windows, you're going to have a bad time. All right. Now also while we're in import land, I want to do our main function because, well, it's pretty rudimentary. We've covered it like to the point of just being ridiculous. So I'm going to say main, main, and we're just going to flesh this out. I'm just going to put a pass in here. Just didn't want to skip any steps. So people watching this don't go, hey, where did main come from? We're going to fill that out as we add in some code. So we're going to do two examples. The first example is going to be a blocking socket. And we've done this before, but I want to do it again just to illustrate what's happening here. So I'm going to say def create underscore the locking. We want a host and an IP. And then I'm going to off the screen here, just grab something to copy and paste to speed this little section up. So I'm going to say logging info, locking, creating socket. Now let's go ahead and create that. I'm going to say socket socket. And then we want a socket dot address family of I net, which is our IP version four. And we're going to go across the internet to my very slow website so we can see in real time, just how blocking works, which means we need a TCP connection because we're going to be working with HTTP. So I want a sock stream. So we're on TCP land. If you skipped any of my videos, I highly recommend you rewind and watch them because we covered all of this so far. Now we're going to say blocking. And I want to say connecting. Anytime I say s dot, whatever we put is going to block meaning this function call that we're going to do is going to hang our program up until it's complete good or bad. So I'm not going to put a lot of try and finalize or any of that other air handling in there. We're just going to assume this code is going to work just for illustrative purposes. So we're going to try to and I need a tuple here. Connect that host IP. Now I want to know that this was connected. And once this is connected, I want to say sending. We're going to go ahead and say s dot send. We want to send some bytes slash r slash. And now the beautiful part about my web server being well rented and slow is that it's going to really show you just how painful blocking sockets can get. So we're going to say blocking and I want to say waiting. On response and you're going to see when I run this that it's going to sit at waiting on response for a long time and actually I'm just going to shorten that. Just say waiting. Once the server responds because it'll eventually time that socket out and spit back some kind of error message is going to say. Here's some info about the error. I don't really care what it was. So I just want to know the length of this. So we're going to grab that. I'm going to say data equals. Go all the way to the front. I want to format this go all the way back here. So I just want to know how much data it actually sent us. From here, we're going to go ahead and close this. Now close should happen very, very quickly. But again, we're blocking so on older older systems, especially like embedded systems that may hang for just a few milliseconds, but it's still blocking. All right, now that we've got all of this assuming I didn't mistype anything. Let's go down here and we're going to run this off my website, which of course is running on port 80. And let's get some screen real estate. See what this looks like in blocking mode. So creating connecting connected sending waiting and it's just going to sit there for a while. This is the painful part of blocking sockets. Eventually it will time out the socket on the server and it's going to send back. Yep, some sort of error message which was 513 bytes and then it's closing the socket down. But again, you see how it kind of step through some steps are faster than others when we got to the waiting part. Our socket is blocking for what well feels like an eternity in computing time because we're just literally not running. This means we're not running our script. Our script is just pretty much frozen in memory until the server responds back. This is really not cool, but this is blocking sockets 101. Now that we understand blocking sockets pretty much in depth, I'm going to make a different example. We're going to do the non blocking socket and this is going to be much more complex. And I'm going to just put a disclaimer right here. This is not what I would consider client ready or industry standard. This is just an example. So it's a very watered down example and it's not a one size fits all solution. So if you're just looking for this for, hey, I'm going to copy and paste this into my production app. Don't do that. This is just a demonstration. All right. Now that we've got that disclaimer out there. I had somebody write me and say, hey, I took your code and paste it into my app and the client complained because in the log it said this is a test. Well, shockingly, would you copy a test code? Anyways, so we're going to create a non blocking. So let's rename that. And let's just switch this logging out to non blocking. The first part of this code really is going to be look shockingly similar. So we've got our socket here. Now we're going to try to connect to the host. So I'm just going to say that thing so far we're not. We're not non blocking, meaning we are still blocking. Let's go ahead and get the return value. Of and I want to go with s.net ex because I don't really care. I want to just get the return value. I'm going to say host and the ports. And this is going to block right here. So this is a little misleading. I just want a very big disclaimer block that way nobody in the internet yells at me, although I get yelled at quite a bit. We're going to say if the return value is not zero, something bad happens. And I want to say failed to connect. And then we're just going to get right out of here. However, if we've gotten to this point, we're going to say connected. And this is where the code's going to get really, really interesting. So I want to take that socket. And I want to set. Locking. Where are you? There you are. False. When we do that, something both magical and horrific happens. Your code will start having a lot of errors if you try working with it in a blocking fashion. And they will be like blocking IO errors and things that make absolutely no sense. So we have to do this a little bit different. We're going to work with the select command and let me scroll way up here. It is horrible to look at. So basically it's going to give us three lists. Things we can read, things we can write and errors. But the select select is going to say, we want to give this potential readers things we could read from. Potential writers, things we could write to potential errors and a timeout. Very important. We give it a timeout. If we do not, this will work in pretty much a blocking fashion. All right. So back down here, we are going to say inputs equals and we want to make a list. We're just going to put that socket in there. Outputs, same thing. Now this is where things get a little bit tricky because we're working with HTTP. We have to send the server information first and then read back a response. So I'm going to say while we have inputs, meaning while we're still expecting some sort of response. Go ahead and grab this. And I'm going to just put the infamous waiting. Now you may be curious why I'm putting waiting in here because I want you to see that this is not blocking. You're going to see that waiting repeated over and over and over to demonstrate we are in a loop. Now we're going to use that select statement. So we want a readable, a writeable, is that even a word? That's not a word. There we go. And I'm actually just going to call this errors. I was going to write exceptional, but we'll be here all day watching me fumble around on the keyboard. I'm going to say select dot select. And we want our inputs. That's just our list of sockets. Our outputs, again, list of sockets and our inputs. Now you may be scratching your head going, whoa, what are you doing here? So remember, things we can read from things we can write to things we're expecting errors on. Again, we're expecting errors on our input, but not our output. Now we have to give this a time out. I'm going to say 0.5 or half a second. If we skip that part, this will block. So we need to put that time out in there. And select select is going to return three iterable items, readable, writeable and errors. And I can actually know what I'm just going to copy and paste it because it's going to bug me. It's different than my notes. Readable, writeable and exceptional that I can say that right. Exceptional. I got to work on my accent. Anyways, let's just go ahead and move forward. What this does though is every time out in this case is 0.5 seconds. It's going to pull the underlying operating system and say, hey, I'm looking for anything that has an input, anything that has an output or anything that has an error. And if you don't have anything, I'm just going to break right out of this. And I shouldn't say break. It's going to reiterate the loop. I'm going to say four s in writeable. Go ahead and pass. And then four s in readable. I'm going to go ahead and pass. And then four s in exceptional. Again, we're going to go ahead and pass. And this is the basic program structure here. So first things first. Once this socket has connected to the server, it should be writeable. So we want to write out to the server. Then we're going to remove that socket so we no longer have something that's writable. And it's still going to be in our inputs list or our readables. And it's going to want to know, hey, tell me server when you send me data. And then once it's readable, we're going to read that data in. And if we have an error, we just want to be able to, well, basically jump right out of this thing. All right, so let's start with our write. And I'm going to back up here. Grab this. Just want to let the user know, hey, we are sending some information. And I want to say send. And again, this is going to be bytes. And I'm going to send the exact same data. Slash r slash on. I'm going to do it a little bit different than the previous one. So I want to say we have now sent this information. Just so we can see the length of bytes, which we have now sent. Now I want to take our outputs and I want to remove that. There's a reason for this because every time this loops, we don't want to tell it, hey, we have a socket we want to output on, or this is going to fire off every single time. So we want to remove that out of there. Finally, let's get rid of that pass because we're not passing. Now we're going to assume that this loops again. And now it's going to say, okay, we gave it an input with a socket in it still. And it is now readable, meaning the server has now sent a response back. So we want to read that response back from the server. And this is all happening asynchronously. So it gets a little bit confusing. So we're going to say reading, I want to say data equal s.recv for receive. Now in our receive, we want to say we want no more than 1024 bytes. Because yes, the server could just slam us with thousands and thousands of bytes and we don't want that. And then we're going to say, we want to know what we got. So we want to know the length of that data. And then I want to close the socket down. And then I want to take our inputs and actually remove that. Because again, when this loops back through, it's going to do that select again. And I don't want that same socket going back through the select because then it's going to just keep continually reading it. Once we get that response back from the server, I am done with this and I don't want to mess with it. Now we're going to say we are done and we're going to break out. I always like that break out kind of reminds me of like 1980s, 1990s break dancing, but we're going to break out. And if we had some sort of boo boo, as I like to call it, we want to notify the user. Hey, there was an error, something bad happened. And we're just going to, you guessed it, remove these things immediately. And if you want to be super conscientious, you can actually break as well. Now you notice one thing this is much, much longer than our blocking. Our non blocking is way more complex. We are doing a loop within a loop within a loop and this gets nuts. So let's go ahead and grab this and see this in action. Go way down here. I'm at this out and assuming I have not mistyped anything, which I'm notorious for mistyping. You'll see non blocking in action and then we'll jump back in and re explain everything. So of course, what did I mess up here? Line 45 create non blocking, can I get it blocking? Port not defined. What do you mean ports not defined? I think every programmer has probably, ah, yes, see, I said host IP. I think every programmer has looked at their output window and what do you mean not defined? All right. So we fixed that silly little error. Let's clear that out and fingers crossed. Uh oh. Hmm. What did we screw up here? So you could see it went very fast until it got to this line 63 create non blocking logging, the data, Lynn data. Object of type int has no Lynn. Hmm. So line 63 has some real time troubleshooting here. Ah, yes. Okay. So let's go ahead and silly me. So send is not going to send us any byte array. It's going to send us an integer. So I was kind of silly that I did link there. Now let's try this. Mistakes abound. There we go. Now you can see that beautiful loop in action. So what's going on is connecting connected waiting and it's sent seven bytes. And now we're waiting for that server to time that connection out. Finally, we had some information on the line. We could read from it and it sent 513 bytes back closing. And you notice our loop stopped and then our script stopped as well. So what's going on here? Let's take this thing from the top. So got rid of a little too much. See if I can get that back. Ah, there we go. All right. So we go into create non blocking. We want an IP version for TCP socket. We get that we say connect EX which basically means I don't care what you do. Just give me back a status code of what you've done. If it's anything other than zero, I want to say we could not connect and let's just jump right out of here. From there, I set the socket to blocking faults, meaning we want this to be asynchronous from this point forward. If you skip that step, this code is going to be kind of funky, but it may actually still work. Now, if you use this and treat it like a blocking socket like you're used to, you're going to get all sorts of blocking IO errors and you're not going to be able to figure out what's going on. And basically that's Python's way of telling you, you need to pull that object in the background. And that's exactly what select does. Every time we loop through this, select is saying, hey, here's a list of things we could possibly get input from. Here's a list of things we possibly may want to write to. And here's a list of things that may give us some sort of headache in the future. Again, I just use the inputs we're going to read from. And you know what? I want this to time out in half a second. You can tweak this to whatever you want. Our first iteration, it's going to say for S in writable, meaning, you know, whatever we've got back here, we should just have one writable socket. So we're going to have blank writable socket blank. So only this is going to run, assuming nothing broke. And that's when we send the data out to the server. And then on the second and third fourth, and it's going to keep polling waiting for that server to turn a response. Once it responds, you'll have a socket, nothing and hopefully nothing. So then readable runs. And you know, so I did a four because these are iterable. So I just wanted to just kind of future proof this code doesn't matter how many readables. And then we're going to go ahead and receive that information, close a socket, remove it. Once we do a select with nothing, nothing, nothing, guess what? It's done looping and we have now breaking out of here. And of course, if we have some sort of error, we're going to say, uh oh, we want to remove everything and break out. Now there are some gotchas here. And I have admittedly overly simplified this to the point of some of the things that I've said probably are either vastly inaccurate or make zero sense because this is actually pretty complex under the hood. So I would highly encourage you to go read the documentation. We are going to do more complex examples in the future and we may and well more than likely touch on some high performance TCP frameworks that are out there. But I wanted to really touch this first because it is so complex. I hope you enjoyed this video. You can find the source code out on github.com. If you need additional help, myself and thousands of other developers are hanging out in the void realms Facebook group. This is a large group with lots of developers and we talk about everything technology related, not just the technology that you just watched. And if you want official training, I do develop courses out on udemy.com. This is official classroom style training. If you go out there and the course you're looking for is just simply not there. Drop me a note. I'm either working on it or I will actually develop it. I will put a link down below for all three of those. And as always, help me help you smash that like and subscribe button. The more popular these videos become, the more I'll create and publish out on YouTube. Thank you for watching.