Home Upgrade Search Memberlist Extras Hacker Tools Award Goals Help Wiki Contact

Python 

Python Chat Server/Client Release/Tutorial

Hey,

Today I'll be showing you how to make a chat server and client in python. But before I do, I'd like to thank ๖ۣۜ1x1x1x1 for his tutorial on networking in python which caught my eye and showed me how awesome python really is. This is my first program in python, so feel free to leave constructive feedback. Note: Even though this was my first program in python, it is by no means my first program. I'm going to assume, you have at least some knowledge of programming.

You can view the full source code here

Now on with the tutorial. We will first be writing the server.
First we will import three things. Go ahead and
PHP Code

<?php 
import socket
import sys
import thread 
Next we will make the socket. The socket is the connection handler. It receives the data the client will send us. The socket is going to be of type TCP (Google this if you need to). We will then bind it to localhost and any random port (should be above 1050). Next we will specify how many clients at most to handle simultaneously.
PHP Code

<?php 
mysocket 
= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "localhost"
port = 9992
numberOfClients 
= 50
mysocket
.bind((host, port))
mysocket.listen(numberOfClients) 
And then some print statements and initializing a dictionary to store connected clients.
PHP Code

<?php 
print '--'
print 'Listening at ' + host + ':' + str(port)
print 
'--'
connected = {} 
After this, I made two functions. The first is called acceptNewConnections and as the name suggests it accepts new connections. I've added comments to show you what the code is doing.
PHP Code

<?php 
def acceptNewConnections
():
    while 
1:#always listen for new connections
        
try:
            
conn, addr = mysocket.accept()#accept a new connection
            
name = conn.recv(1024)#the first connection will always be the name (done client sided)
            
if name:#checks to make sure the client did send something
                
if name in connected:#check if name is taken by someone already
        
conn.send('SERVER:NAME CHOSEN')#If it is taken tell that to the client
        
conn.close()#close the connection
                
else:#if name isn't taken
        
print name + ' Connected'
        
connected[name] = (conn, addr)#add the connection to the dictionary with key being name
        
print str(len(connected)) + " Users connected"
        
thread.start_new_thread(listen, (connected[name][0], connected[name][1], name))#starts the thread which will listen to connections from that socket.
        #if you don't know what threads are, they allow for your program to do more than 1 thing at once.
        
connectedNames = ''
        
for nameF,connF in connected.iteritems():#loop through the connected clients to tell new user joined
        
if not nameF is name:#make sure the new user isn't being told he joined
        
connF[0].send(name + " Joined the chat")
        
connectedNames += nameF + ', '# add the name of connected user to connectednames string
        
conn.send('SERVER:There are currently ' + str(len(connected)) + ' connected users: ' + connectedNames + name + '\nType ::help for help')
#send new user welcome message
        
except Exception, e:
            print 
'Erroraa ' + str(e)
            
pass 

The second function I made was the listen function. This one also has comments to help you out:
PHP Code

<?php 
def listen
(conn,addr,name):#takes in the connection, the ip adress of connection and name as parameters
    
while 1:#always listens to specified client
        
try:
            
data = conn.recv(1024)#receives data with 1024 buffersize (if you don't know what it is leave it as is)
            
print str(data)
            for 
nameF,connF in connected.iteritems():#loop through connected clients
                
if not nameF is name:#make sure the client isn't the same one who send the data
        
connF[0].send(data)#send the data to the other user
        
except Exception, e:
            if 
'10054' in str(e):#this error means the connection is closed
                
print name + ' Left'
                
del connected[name]#delete the connection from the connected dictionary
                
for nameF,connF in connected.iteritems():#loop through connected clients
        
connF[0].send(name + " Left")#tell them that the user left
    #notice there is no if here because I've already deleted the current connection from the connected dictionary
                
thread.exit()#stop the thread
            
else:
                print 
str(e)
                break 
Lastly, I started the acceptConnections Thread and set a while loop to keep the main thread running as well:
PHP Code

<?php 
try:
    
thread.start_new_thread(acceptNewConnections, ())
except Exception, e:
    print 
str(e)
    print 
"Error: unable to start thread"

while 1:
    
pass 

Now the Client:
Again start with the imports:
PHP Code

<?php 
import socket
import thread
import sys 
Now here I defined the two main functions first. The first function is the send function which listens for user input and sends it to the client.
PHP Code

<?php 
def send
():
    while 
1:#always listen for input
        
str = raw_input("")#gets input from user
        
try:
            if 
str == '::exit':#checks if str is a command to exit
                
mysocket.close()#if it is it's going to close the socket
                
sys.exit(0)#and exit the program
            
elif str == '::help':#else if the str is another command for help
                
print '\nHelp: \n\tTo exit tpe ::exit'#print help (you can add more stuff/commands if you'd like)
            
else:
                
mysocket.send(name + ": " + str)#send the server the name of the client + message 
        
except Exception, e:
            if 
'10054' in e:#means the server went offline
                
raw_input('Server disconnected. Press enter to exit')
                
sys.exit(0) 
The next function is the listen function. This method listens for the data from the server and prints it.
PHP Code

<?php 
def listen
():
    while 
1:#always listen
        
try:
            
data = mysocket.recv(1024)#get the data
            
print ">>" + data#print it with >> to show it's from the server/another user
        
except Exception, e:
            if 
'10054' in str(e):#if server went offline:
                
raw_input('Server disconnected. Press enter to exit')
                
sys.exit(0) 
Above, I defined the functions. However, I haven't called them or done anything else with the program yet. Now I'll make a socket and try to connect to the server:
PHP Code

<?php 
mysocket 
= socket.socket(socket.AF_INET, socket.SOCK_STREAM)#make a new TCP socket in the IPv4 protocol
mysocket.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 30000, 30000))#make it so that it doesn't die out anytime soon. 
#TCP sockets close after a certain amount of connections, here I set the amount to be 30000
host = "localhost"#server to connect to
port = 9992#port
try:
    
mysocket.connect((host, port))#try to connect to the server
except Exception, e:
    print 
'something\'s wrong. Exception type is %s' % (`e`)
    
raw_input('Can\'t connect. Press enter to close')#can't connect so close
    
sys.exit(0) 
Now that I'm connected, I have to set my name and make sure it's available:
PHP Code

<?php 
name 
= raw_input('Please enter your name: ')#ask user for the name
mysocket.send(name)#send it to the server
data = mysocket.recv(1024)#receive the response
while 1:
    if 
'NAME CHOSEN' in data:#see if response tells us if the name is chosen
        
mysocket.close();#if it is first close the current socket
        
mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#remake the socket
        
mysocket.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 30000, 30000))#reset the minimum connection value
        
try:
            
mysocket.connect((host, port))#connect to the server again
        
except Exception, e:
            print 
'something\'s wrong. Exception type is %s' % (`e`)
            
raw_input('Can\'t connect. Press enter to close')
            
sys.exit(0)
        
name = raw_input('That name is chosen. Enter a different name ');#ask for the name again
        
mysocket.send(name);#send the name again
        
data = mysocket.recv(1024)#reset data to equal the response and go back to the top of the loop
    
else:#if name is available
        
print data#print the welcome message
        
break#get out the infinite loop because the name is available and we are connected 
Now that we are connected all we have to do is start the listen and send threads:
PHP Code

<?php 
try:
    
thread.start_new_thread(send, ())#start the send thread
    
thread.start_new_thread(listen, ())#start the listening thread
except:
    print 
"Error: unable to start thread"

while 1:#keep main thread running
    
pass 

Feel free to pm me for help or post here. As a challenge, you should try to add private messaging.
It only takes 2 seconds to say thanks.
It actually took me longer than two seconds to say thanks, but this is a nice contribution.
★ Qwazz has given me AIDS!

* Everything posted on this account is false. I do not condone drug usage or extraction. All pictures are made in photoshop and every post is made of fictional content.
Good tutorial. I only wonder why you changed the condition in the while loop every time you used one.
I'm still fairly new to python, and this is definitely a project I'm going to try to tackle when I'm a little more experienced. Bookmarked.

Oh and seeing this, infinite loops are okay in python? Because coming from php those are almost always a no-no.
Nice tutorial. Everything explained and well divided 😁 .

Just a few remarks:
1: The code is pretty long and reading it inside php code tag gave me a headache. Maybe posting the source on pastbin and add the link at the end of your tutorial?

2: Try to separate comments from the code. (Maybe hackforums destroyed your indent, but hey! that's another reason to post it on pastebin!)
ie:
Code
mycode [this is a place holder so hackforum wont destroy my indent] . . mycomment
while i_have_a_cookie: [this is a place holder so hackforum wont destroy my indent] mycomment
etc...

This 🙃:
Code
#Nope
while 1==1:
#Good!
while 1:
(Dec 16, 2013 09:26 AM)dberube Wrote:  Nice tutorial. Everything explained and well divided 😁 .

Just a few remarks:
1: The code is pretty long and reading it inside php code tag gave me a headache. Maybe posting the source on pastbin and add the link at the end of your tutorial?

2: Try to separate comments from the code. (Maybe hackforums destroyed your indent, but hey! that's another reason to post it on pastebin!)
ie:
Code
mycode [this is a place holder so hackforum wont destroy my indent] . . mycomment
while i_have_a_cookie: [this is a place holder so hackforum wont destroy my indent] mycomment
etc...

This 🙃:
Code
#Nope
while 1==1:
#Good!
while 1:

Thanks for your feedback. I'll change the code now. As for tutorials, yes I had to add it on the second line because the page became really long in the horizontal direction if I kept some comments on the same line. I really don't want to use pastbin, I'd rather keep it on HF.
woww thx alot for that tutorial! i just told me to try doing something like this the next days and then see your tutorial :D

But i have to agree with dberube. It was really awesome if you could upload the whole Server and Client program!
Code
mysocket.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 30000, 30000))#make it so that it doesn't die out anytime soon.
Returns: AttributeError: '_socketobject' object has no attribute 'ioctl'
There are other ways to make a socket not time out , just letting you know, and Im running python 2.7.3.
If you want another challenge you can add AES encryption to it using https://www.dlitz.net/software/pycrypto/
Nice tutorial


(Dec 17, 2013 04:12 AM)Ne0nWorm Wrote:  
Code
mysocket.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 30000, 30000))#make it so that it doesn't die out anytime soon.
Returns: AttributeError: '_socketobject' object has no attribute 'ioctl'
There are other ways to make a socket not time out , just letting you know, and Im running python 2.7.3.

It's windows only.
[Image: tAgt9WA.png]
(Dec 17, 2013 04:30 AM)blem Wrote:  If you want another challenge you can add AES encryption to it using https://www.dlitz.net/software/pycrypto/
Nice tutorial



It's windows only.
[Image: tAgt9WA.png]

Thats why i stated there are other ways to keep a socket alive :)
It's been a while since this has been on the first page. A lot of newcomers might find this useful.
Like the guy said on the first page I am also quite new to Python but I hope to tackle project like this in the future.
(Mar 19, 2014 09:35 AM)#BORNE Wrote:  Like the guy said on the first page I am also quite new to Python but I hope to tackle project like this in the future.

Honestly, python is an easy language. I wrote this in my first day of learning python. I hope you find this useful.
HF fucked your indentation and again as dberube said, it gives people a headache to read that much code in php tags.

Granted using the addition operator for string concatenation is a bit childish when you could use .format or strf syntax don't you think?
actually good one - only wrong stuff I noticed (apart Win only stuff which was already mentioned) is "Next we will specify how many clients at most to handle simultaneously." - that specifies, how many pending connection requests are possible (and according to documentation is usually maximum possible 5), not how many clients there can be altogether

( I'm slightly disappointed, though - after half a year back to HF, I open randomly tutorial on first page of python section, looking forward to see some really bad stuff again, then even reading "This is my first program in python" and telling myself "yeah, nothing changed, again some noob writing tutorial, even though he knows shit" and then actually above average client-server tutorial...)


Possibly Related Threads...
Thread / Author Replies Views Last Post
[Java] by OneHalfApr 30, 2026 12:09 PM 7 479 Apr 30, 2026 12:09 PM
Last Post: APIBoy
[C] by HackersMar 6, 2024 09:02 AM 4 187 Mar 6, 2024 09:02 AM
Last Post: Hackers
[Python] by Bass_ReevesAug 20, 2023 01:44 AM 9 632 Aug 20, 2023 01:44 AM
Last Post: Lucky4L