Real-Time Desktop chat application using Python

In this post i will show you how to create a Desktop chat application using python, packages used for this project are socket, time, threading, Tkinter, a short demo of this project is shown below

The aim of this project is to create a Gui Desktop chat application that will work on the same network, both users can connect by pressing the start chat button

Installating Required Packages

pip install socket

Code Explanation

Let’s import our required libraries first

import socket
import time
import threading
from tkinter import *

socket is used to establish the connection between two systems, as we are performing two tasks simultaneously we need threading to create a separate thread for each task, and Tkinter is used to create our GUI, lets start by creating the Gui

root=Tk()
root.geometry("300x500")
root.config(bg="white")


startchatimage=PhotoImage(file='start.png')

buttons=Button(root,image=startchatimage,command=func,borderwidth=0)
buttons.place(x=90,y=10)

message=StringVar()
messagebox=Entry(root,textvariable=message,font=('calibre',10,'normal'),border=2,width=32)
messagebox.place(x=10,y=444)

sendmessageimg=PhotoImage(file='send.png')

sendmessagebutton=Button(root,image=sendmessageimg,command=threadsendmsg,borderwidth=0)
sendmessagebutton.place(x=260,y=440)

lstbx=Listbox(root,height=20,width=43)
lstbx.place(x=15,y=80)

user_name = Label(root,text =" Number" ,width=10)

root.mainloop()

We are initializing our Tkinter window by creating Tk class instance with the variable name root, then we are specifying what is the geometry or what is the height and width of GUI then we are specifying the background color of our GUI, we have 5 widgets in our Gui (You can download the images from our GitHub repository ) let’s create them one by one

  • Start chat Button : this buttton will be used to connect two user for chat, lets see how we can create it, startchatimage variable will store the image data by using PhotoImage() class of tkinter parameter being the image path,then we will create the button using Button class with following parameters
    • tkinter class instance
    • image on the button (you can also define text here)
    • command(function) that this button will trigger
    • width of the border of the button

startbutton is then placed using place class parameters are x and y coordinates at which you want to place the button

  • message box : this is small rectangular text area where we will write text that we want to send, this is basically a entry widget with following parameters
    • tkinter class instance
    • text variable
    • font size and style
    • border width
    • width of entry box

message box is then placed at desired x and y coordinates

  • Send message Button : This button is pressed when user wants to send the message paramters are same as start button with a few changes
    • function triggered is different
    • button image is different
    • coordinate at which button to be placed is different
  • Message Box : This is where all the messages will appear from both the users its a listbox widget with following parameters
    • tkinter class instance
    • height and width of listbox

lastly, we will close the mainloop as our GUI is completed, after completing the frontend let’s jump backstage and complete what’s happening behind.

def func():
	t=threading.Thread(target=recv)
	t.start()

to start the connection we press the start chat button that we have already discussed above in the frontend part, this button will trigger func() function, this function will create a separate thread that will continuously run in the background checking for new incoming messages, target for this thread is recv function, now lets see what inside this recv() function

def recv():
	listensocket=socket.socket()
	port=3050
	maxconnection=99
	ip=socket.gethostname()
	print(ip)

	listensocket.bind(('',port))
	listensocket.listen(maxconnection)
	(clientsocket,address)=listensocket.accept()
	
	while True:
		sendermessage=clientsocket.recv(1024).decode()
		if not sendermessage=="":
			time.sleep(5)
			lstbx.insert(0,"Client : "+sendermessage)

first, we create a socket instance with the variable name listensocket, port value is the port number of the system you want to chat with, maxconnection is the maximum number of incoming connections, ip will store the host ip which we will use to connect on another system after the connection is received we will bind it with our system using the port number of the second system, we are listening to the connection up to a maximum limit defined by maxconnection variable, after this, we are finally accepting the incoming signal with client socket and address, now to keep this constantly running we are running an infinite while loop inside which we will first decode the message and if the message is not empty we will add time delay of 5 seconds and then insert the message into our listbox, soo this was how we can receive the messages now lets see how we can send one

def threadsendmsg():
	th=threading.Thread(target=sendmsg)
	th.start()

In the frontend section, we created the entry widget and send button so the send button will trigger threadsendmsg() function which will create a separate thread for sending messages and we will do that inside sendmsg function

s=0

def sendmsg():
	global s
	if s==0:
		s=socket.socket()
		hostname=''
		port=4050
		s.connect((hostname,port))
		msg=messagebox.get()
		lstbx.insert(0,"You : "+msg)
		s.send(msg.encode())
	else:
		msg=messagebox.get()
		lstbx.insert(0,"You : "+msg)
		s.send(msg.encode())

we will first create a variable outside the function this variable will be used to run a few instructions only once which I will explain later in this paragraph only, inside the function we will call the variable from outside and check if the value is equal to 0 and if it is we will create socket instance define the port and connect with the system after this we will extract the data from our entry widget using .get() command and after inserting the message in the Listbox to make it look like a chat between two people we will send the message to the connected system so these commands will run when the value of s=0 now if you look closely we are using s variable for socket also so this means after the first time variable is not 0 so else condition will be executed from now, inside else we have everything same except the connection is already established so we will simply get the message from entry box insert in Listbox and send it to receiver

The exact same program is present on the second system also only with a few changes

  • changing the port number
  • changing the hostname

for a more detailed explanation watch this video

Complete Code

import socket
import time
import threading
from tkinter import *

root=Tk()
root.geometry("300x500")
root.config(bg="white")

def func():
	t=threading.Thread(target=recv)
	t.start()


def recv():
	listensocket=socket.socket()
	port=3050
	maxconnection=99
	ip=socket.gethostname()
	print(ip)

	listensocket.bind(('',port))
	listensocket.listen(maxconnection)
	(clientsocket,address)=listensocket.accept()
	
	while True:
		sendermessage=clientsocket.recv(1024).decode()
		if not sendermessage=="":
			time.sleep(5)
			lstbx.insert(0,"Client : "+sendermessage)


s=0

def sendmsg():
	global s
	if s==0:
		s=socket.socket()
		hostname=''
		port=4050
		s.connect((hostname,port))
		msg=messagebox.get()
		lstbx.insert(0,"You : "+msg)
		s.send(msg.encode())
	else:
		msg=messagebox.get()
		lstbx.insert(0,"You : "+msg)
		s.send(msg.encode())


def threadsendmsg():
	th=threading.Thread(target=sendmsg)
	th.start()




startchatimage=PhotoImage(file='start.png')

buttons=Button(root,image=startchatimage,command=func,borderwidth=0)
buttons.place(x=90,y=10)

message=StringVar()
messagebox=Entry(root,textvariable=message,font=('calibre',10,'normal'),border=2,width=32)
messagebox.place(x=10,y=444)

sendmessageimg=PhotoImage(file='send.png')

sendmessagebutton=Button(root,image=sendmessageimg,command=threadsendmsg,borderwidth=0)
sendmessagebutton.place(x=260,y=440)

lstbx=Listbox(root,height=20,width=43)
lstbx.place(x=15,y=80)

user_name = Label(root,text =" Number" ,width=10)

root.mainloop()

About the author

Harshit

Hey, I'am Harshit Roy, a programmer with an obsession of learning new things, this blog is dedicated to helping people to learn programming fun way by creating projects

View all posts

1 Comment