Simple TCP Chat Room in Python

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what is going on guys welcome to this video in today's episode we're going to develop a tcp chat in python so we're going to set up a server and we're going to set up multiple clients and these clients can then connect to the server which works as a chat room you could say and each client can then send messages to the server with his or her nickname and all the other clients can see these messages and respond so let us get into the code now before we actually start programming as always i need to mention that we have a blog post on neuroonline.com here so if you're interested in a text-based version of this tutorial you can just check out the blog post on neural9.com now the first thing we're going to do is we're going to create a server file so we're going to right-click onto the directory and create a server.py file and in here we're going to import threading import threading and import sockets these are the two modules that we're going to need in this video and if you don't know how to work with sockets or you don't know what sockets are you don't know what multi-threading is i highly recommend that you check out the python intermediate tutorial series on this channel because there i talk about network programming about multi-threading what these things are i also have a tutorial on how to make a port scanner a multi-threaded port scanner where i use both concepts so check out these videos uh because i'm not going to go too much into the details of threading or sockets in this video now the first thing we need to do here is we need to define a host address and a port for our server so the host in this case will be just uh 127.0.0.1 because we're using localhost so let's add a comment here localhost this is just because we are running this on our machine if you run the server on a web server you should always uh pick the host address of the server so always the ip address of the server uh this is just the basic local host since we're running it on this computer it uh will be localhost then we need a port and as a port you can choose whatever you want you could just go with 99872 or something like that what you shouldn't do is you shouldn't take ports like 80 because this is http you should just not pick any reserve ports or well-known ports at all so uh just don't choose any ports from one to i don't know i think 10 000 or something but we're just going to go with 55 555. this is a solid port um and then what we need to do is we need to start service so we're going to say server equals socket.socket and in here we're going to say it's an internet socket so socket.af inet and then we're going to say it's uh suck socket.stream so again if you don't know what that means uh oh sorry socket dot suck stream if you don't know what that is and if you don't know uh why we're creating a socket in that way check out the intermediate tutorial series they will talk about these concepts so next thing is we need to bind the server to the host and the ip address so we say server.bind and we pass a tuple of host and port so we're saying okay the server is bound to the local host on port five five five five five five i think this was five times fives hopefully uh then we say server.listen which basically puts our server into listening mode for new connection so as soon as we say server.listen the server starts listening for incoming connections now what we're going to do next is we're going to define a couple of methods we're going to define three methods the first one being a broadcast method the second one being a handle method for client connections and the last one being a receive method which basically combines all the methods into a main method you could say but before we do that we're going to define two empty lists here and these two empty lists are the clients list and the nicknames list so these two lists will be the list uh where we put all of our clients in so if we have a new client connecting to the server we're going to put it into the clients list and also we're going to get the nickname of this client which the client can then later on choose and we're going to say okay the client x has the nickname uh i don't know bob or something like that uh and then we can just use clients and nicknames to do certain things later on now the first function we're going to define here is the broadcast function is a very simple function it's just a function that sends a message to all the clients that are currently connected to this server so i'm going to say def broadcast and we're going to pass a message here so we're going to say broadcast message and then we're just going to see for every client in the clients list which now is empty but later on we're going to fill it up for every client that is now connected to the server we're just going to say client dot sent this message very simple we're just getting all the clients and sending a particular message and this is how you broadcast messages from a server to all the clients so the next thing that we want to do is we want to handle the client connection so when a client connects to the server we want to receive messages from the client if the client is sending any and then we also want to uh send back messages to all the other clients depending on what the client sends so if client a says hi we want to get this message process it and then broadcast it to all the other clients including uh also client a itself because every client needs to see what's happening in the server so what we want to do is want to find a handle function and we want to handle one particular client so we're we're going to later on run this function on all of the individual clients but for now we're just handling one uh single client so we're getting the client and what we do is we say while true basically we're starting an endless loop here we're saying try a certain thing so as long as it works without giving you an exception or an error we're going to just say message equals client dot receive i think it's like that our ecv uh 1024 bytes just the basic method message so what we do here is we say okay as long as it works that we receive a message from the client we're just going to broadcast it to all the other clients or oh sorry no broadcast a message to all the other clients so what we're doing here is we say try to receive a message from the client and if that succeeds broadcast this message to all the other clients including this client as well if that doesn't work so if we get some exception some error while receiving the message or while broadcasting what we're going to do is we're going to just uh cut the connection to this particular client remove it from the list and then uh basically terminate this function so we're going to say or terminate this loop so we're going to say the index of this particular client is the clients.index of this client and we need this index in order to remove the nickname and the client from the list so we're just getting the index of key where is this particular client that failed right now in the list which index does it have and then we're going to say clients.remove client so we're going to just remove the client we're going to close the connection to the client and then we're also going to say okay the nickname of this client is the nicknames in index of the client so basically whenever we're adding a client we're also adding the nickname so they will always have the same index and when we remove a client we also remove the nickname on this particular index so that we don't get any inconsistencies here so what we do then is we say nicknames dot remove our nickname and you could either print it before that i'm going to print it before that or you can print it afterwards we're just going to broadcast to all the clients that this client has now left so we're going to say broadcast and we're going to use an f string here and we're going to say nickname uh left the chat for example um and then we're going to encode this message in ascii code so that we get the right message so after that of course we're breaking out of the loop and that's it so we're handling a client one client connects and what we're doing is we're constantly trying to get messages from this client uh this will not give you an error if the client is not sending anything but it will give you an error if this client is not there anymore so as soon as a client uh produces some kind of error what we do is we just remove it from the list remove the nickname and broadcast to all the different uh clients connected to the server that this client is now left and then we just terminate this function so this function will later on run in a thread for each client we'll have a single thread running and processing this particular function or actually executing the handle function and as soon as a client disconnects what we do is we just break this loop and therefore terminate the function therefore terminate or end the threat so this is how we're going to handle the client connection so now last but not least in the server what we're going to do is we're going to define the main method the receive method which combines all these things that we've written up until now into one function so we're going to say def receive and we're going to just receive client connection so we're saying while true what the server is doing it is basically accepting all the connections so we're going to say client and address equals server.accept so what's happening is we're running the accept method all the time and if this method gets a connection what we get what it returns is a client and the address of the client so in this case we're always going to have the same address since we're on one computer but if you have this running on a server you'll see the address the ip address of this client connecting to your server so basically we're connecting to clients or we're allowing the clients to connect and if this is done if this happens if a client connects we're just going to say print on the server itself this is not a broadcast this is just on the server console so that we see what's happening um it with and let's make an f string out of this connected with address so that we know actually we should say str address double d there you go so we're waiting for a connection we're accepting all the connections coming and if a connection happens to come in fact come in this moment what we do is we just print that we now connect it to this client on this particular address and then of course what we want to do is we want to get the nickname of the client so the client will be able before it connects to our server to choose a nickname and it will then it will then be the nickname that is displayed on the server uh so what we need to do first is we need to ask the client for the nickname because of course if it just sends us a message we're going to process it but the first message that the client sends to us should be the nickname so what we're going to say is we're going to send a message to this client and this message will be a code word which is not visible to the user of the client it's just visible to the client itself later on in the code we're going to send the keyword nick and if the client receives this keyword nick it should be um it should be informed that it should send the nickname to the server so that the server knows who are you we're going to say encode ascii again and we're basically just sending this keyword and in the next step what we hope to receive from the client is the nickname itself so we're going to say client dot receive and we're going to receive 1024 bytes and decode them from ascii so then of course what we're going to do is we're going to say nicknames dot append nickname and clients dot append client and then what we need to do is we just need to send a couple of messages here so we're going to say okay print nickname of the client is okay so there you go nickname of the client is and then nickname of the k9 of the client just connected is whatever and then we're just going to broadcast that so that everyone every client is currently connected to the server knows that this client is now connected and that's the nickname of this client so we're just going to say f string um joined the chat and we're going to encode this message again and then every server sorry every client knows that there is a new client in this chat and they get a message that this client just joined the chat with the respective nickname and then we're going to send the particular client that just connected we're going to send to the one client that this client connected to the server so we're going to say sent uh connect it to the server so that the client knows that it's now connected and it can start chatting and of course we're going to encode this message as well now we're almost done the last two things that we're going to do is we're going to define a thread and run a thread so we're going to say threat as we said we're going to run one thread for each client connected because we need to handle them at the same time we cannot just handle them serially because uh one client might send something and another client might send something and we need to process it at the same time or at least roughly at the same time and not just you know process one client interaction then start with the next one uh so what we're going to do is we're going to say threading dot threat capital t and the target of this thread will be the handle function and the arguments will be just client and then we're going to say thread dot start and if you know about if you know how to deal with python threads you know that you need to use the start method and not the run method because otherwise this doesn't work so let's uh look one more time at this code what we're doing is we're just saying accept clients all the time when a client actually connects we're going to just say okay connected with this client so that the server admin knows what's happening then we're going to send to the client the keyword nick or the code word nick so that the client knows okay i need to send my nickname we're then going to receive the nickname from the client append this nickname and this client to our lists and then we're going to print on the server again for the server admin that the nickname of this client is whatever then we're going to broadcast to all the clients connected to the server that this client with this nickname now join the chat we're going to send a message to the particular client that the connection was successful and then we're going to start a thread handling the connection to this particular client so now we can actually start coding the client but before we do that i need to add one more line here the receive method also needs to be called because we defined all this but we didn't run it so the receive method is our main method and it runs down here we could actually also go ahead and run the server but you're not going to see anything but a good sign is that it's running and not crashing so it probably works but for the server to do something of course we need a client to connect to it because otherwise it's not going to do anything what we could do is we could just print out the message server is listening listen dot dot dot and then it yeah you can see the server is listening and that's how you run the server now the next thing is we need to define the client so we're going to say client dot py and here also we're going to import socket and import threading and we're also going to define a socket so we're going to say client equals socket dot socket af oh sorry socket dot af by net and socket dot sock stream there you go and now instead of binding the client to our a port and a host we're going to connect it to a host on the port so we're going to say client dot connect and we're going to connect it to localhost so 127.0.0.1 and we're going to connect it on port 55555 and now we're connecting it to the server so in this line when this line gets executed the server will receive uh will trigger the accept method and the client is now connected to the server so what we're going to do in this client is we're going to define two methods and run two threads simultaneously so we're going to receive all the time data from the server so we're going to have a receive function that's running constantly and at the same time we're going to um to send messages or we need a thread running for all the messages that we're going to send so let's start with the receiving part define a function receive and this function is just running again in a while true loop and we're going to try something all the time what we're going to try is we're going to receive messages from the server so in this case we'll say client.receive but the client is actually receiving from the server so what we're going to do is we're going to say message equals client.receive just don't get confused we're still receiving from the server not from the client but for the server to send messages it uses a client so it could be considered a client so we're receiving 1024 bytes and we're decoding what we receive and that's basically it now what we need to do is we need to check if the message that we just received is nick or something else so we're going to say okay if message equals nick which is the keyword for sending the nickname we're going to send the nickname i'm just going to pass here because we need to uh get the nickname first in the beginning of the script and if it's not nickname what we're going to do is we're just going to print the message so whenever we get a message from the server that's not nik or any other keyword that we define we're just going to print the message because we're not going to do anything about it we just want to see what the server has to tell us so we're going to say message print or print message if that doesn't work what we're going to do is we're just going to close the connection so we're going to say uh an error occurred and i think double r i'm not sure oh man i think it's misspelt yeah double r uh an error occurred and uh then we're just going to close the connection so we're going to say client close and we're going to break this endless loop now how are we going to send the nickname first of all we need the nickname so we're going to say nickname equals input choose a nickname so whenever we run a client the first thing that we want to do is we want to choose a nickname and if the message equals nick what we're going to do is we're going to say client dot sent and we're going to send the nickname the encoded version to the server so what's happening here is the server is listening all the time the client is choosing a nickname connects to the server and the moment this happens this gets triggered we say connected with whomever and the first thing that the server then does is it sends the keyword nic so we're going to get the keyword nick we're going to send the client name or the nickname then we're going to receive it here append it and whatever and then we're having a connection and as soon as the server sends something to us we're going to receive it and print it onto our screen now let's finish off the client by defining the second function which is the write function and what this function does is it runs a while loop as well in endless loop and here what we do is we always define a new message so we're going to say message equals um f string and here we're going to say nickname colon and then the actual message the actual message is always what the user puts into the script so oh i need to use double quotation marks here what we're doing here is we're constantly running new input functions so as soon as the user clicks enter and sends one input we ask for the next one so the user the only option that the user has is to either close the client or write new messages so you're always waiting for new messages this is a threat receive and write will run simultaneously and the right function is always waiting for a new message and you send a message by clicking the enter key and once you get a message so once you click enter or press enter what happens is you say client dot sent and we're sending the message of course encoded and that's basically it that's the whole function and now what we need to do is we need to run two threads we need to run a receipt thread and a right thread so we're going to say receive thread equals uh threading dot thread with the target function of receive we don't need any arguments here and then we're going to say receive thread dot start and then we're going to do the same thing for the writing thread so right thread equals threading dot threat and a target here is the write function and we're going to start this thread as well and now we're done with that but uh the problem here is that in pycharm we can only run uh one client at a time and to see how this works we need to run one server and two clients so i'm going to run this in a command line right now so right here i navigated three terminals into the direction of the tcp chat and what i'm going to do on the left side here this will be a server and these two right terminals here are going to be um the clients so i'm going to just say python server dot py and as you can see server is listening and here we're just going to say python client and we can choose a nickname so for example let's say neural nine is the nickname and as you can see we get connected with the ip address and the port nickname of the client is neural nine i can see here on the right neural nine jointed chat because this is a broadcast message that gets sent to all the clients including myself and also connected to the server and now we can run a second client so we say python client.py and i can choose a nickname here let's say youtube audience so you guys and you can see i get here again connected nickname is youtube audience here i see youtube audience joined the chat connected to server and here on neural nine i can see uh youtube audience joined to chat so i can say hi or hey youtube and then what happens here in the server i don't see anything because the server is just monitoring the connections and here on the client side i see hey youtube from myself but also the youtube audience here sees hey youtube from neural nine so it can answer hey what's up and i can also see it up here and i can also start spamming here if i want and you'll see it in both uh clients so this is how you do a professional advanced chat of course you could also add some special commands like kik or ban or i don't know emojis or something but this is a basic version of a chat room now that's it for today's video i really enjoyed this project and i think it's pretty cool if you want to see more about this project so if you want me to add more features like kicking or banning or anything like that let me know in the comments maybe i'll do a part two or part three on this and extend this chat into something bigger uh if you want that let me know otherwise if you enjoyed this video if you learned something hit the like button let me know in the comments and if you have questions feel free to ask them in the comments down below also to give feedback uh and of course if you haven't done it yet subscribe to this channel to see more future videos for free so thank you very much for watching see you in the next video and bye [Music] you
Info
Channel: NeuralNine
Views: 71,334
Rating: 4.9688959 out of 5
Keywords: python, programming, coding, tutorial, tcp chat, chat room, tcp chat room, networking, sockets, threading, multithreading
Id: 3UOyky9sEQY
Channel Id: undefined
Length: 25min 38sec (1538 seconds)
Published: Fri May 01 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.