Tutorial write a multithread chat in Python – update
Posted on mai 30, 2008 under Python | Comments are off
This is my first post in English, sorry any is grammatical errors !!!
My intention is write a little tutorial in Python showing how to make an oriented objects chat server using sockets and threads.
A skeleton of the chat server is basically given by the following loop:
- Wait for client connection
- After the client to be connected start a thread to each new client
- Get the user name and nickname
- Entry in a loop to read the socket if exists new messages send all clients except client who generated the message
Let’s begin by waiting client connection
The following snippet of code creates a socket of type stream at line 1, and associate it with the server socket at port 5800 line 4, finally listen for new connections at line 7.
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
try:
serversocket.bind(('',5800))
except ValueError,e:
print e
serversocket.listen(5)
Until now we have one server socket listening at port 5800, but it is not allow client connections. When connection request arrives, the server decides if it will be accept. In order to accept a connection the method accept() should be invoked. This method doesn’t take parameter and return a tuple (clientsocket, address), where clientsocket is a new socket server used to communicate with the client and address is the client address. The following snippet of code illustrates one loop waiting by new clients.
while True:
(clientSocket, address) = serversocket.accept()
At this moment we have one server socket waiting for new connections. Now we have to write a client class which will be inherit methods and attributes by the thread class. In order to know all clients connected at the server we will be storing the client socket at a List.
Well, now we will write a class Client that inherits a class Thread and will have the following methods:
sendAll() to send messages for all clients except a client that send messages;
newClientConnect() this method gets the user name, nick and stores at a sockets List ;
printHelp() show how to use chat;
run() This is the main thread method where the client.start() method will be invoked it will by each client, and perform tasks how: read socket, verify if the message have commands, after that, send messages for all clients.
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
# This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; version 2 of the License.
# This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#author: Marlon Petry
#Date: 2008/04/30
#Function: Chat server in python
#
import sys
from threading import Thread
import socket
allClients = []
class Client(Thread):
def __init__(self,clientSocket):
Thread.__init__(self)
self.sockfd = clientSocket #socket client
self.name = ""
self.nickName = ""
def printHelp(self):
str = "======================================\n"
str = str + "Chat Help\n\q quit\n"
str = str + "======================================\n"
return str
def newClientConnect(self):
self.sockfd.send("Welcome my first chat\n")
self.sockfd.send("Login: ")
name = self.sockfd.recv(2048)
self.name = name.strip()
self.sockfd.send("NickName: ")
nickName = self.sockfd.recv(2048)
self.nickName = nickName.strip()
allClients.append(self.sockfd)
def sendAll(self,buff):
for index, clientSock in enumerate(allClients):
if self.sockfd != clientSock:
print (self.sockfd == clientSock)
try:
s = clientSock.send("[%s] => %s"%(self.nickName, buff))
except socket.error,e:
print "error socket %s\n" % e
clientSock.close()
del allClients[index]
def run(self):
self.newClientConnect()
while True:
buff = self.sockfd.recv(2048)
if buff.strip() == '\q':
self.sockfd.close()
break # Exit when break
elif buff.strip() == '\?':
str = self.printHelp()
self.sockfd.send(str)
else:
self.sendAll(buff)
if __name__ == "__main__":
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
try:
serversocket.bind(('',5800))
except ValueError,e:
print e
serversocket.listen(5)
while True:
(clientSocket, address) = serversocket.accept()
ct = Client(clientSocket)
ct.start()
__all__ = ['allClients','Client']
How to use
Start server
python server.py
Connect client
telnet 127.0.0.1 5800 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Welcome my first chat Login: Hi NickName: uhuuu
Connect more clients for test
Thats all Folks!!!!!!!!
References:
Python Network Programming, Sebastian V. Tiponut, Technical University Timisoara
Special Thanks to my friends Milton Rocca and Marco Antonio de Castro Barbosa.
