How to Write a chat room in Python and a chat room in Python

Source: Internet
Author: User

How to Write a chat room in Python and a chat room in Python
I. course Introduction 1. Introduction

This project class is used to implement the server and client of Simple Chat Room programs.

2. knowledge points

The server involves the asyncore, asynchat, and socket modules. The client uses the telnetlib, wx, time, and thread modules.

3. Required Environment

WxPython is required to compile the client in this lesson. It is a GUI toolkit. Use the following command to install it:

$ sudo apt-get install python-wxtools

The password is shiyanlou.

4. Project Effect

Logon window

Chat Window

5. Download source code
git clone https://github.com/shiyanlou/pythonchat.git

Description: If you do not understand the download method of the above Code or cannot find the code in the environment after the download, click here

Ii. Project Practice (server side) 1. Server Type

First, we need a chat server. Here we inherit the asyncore dispatcher class for implementation. The Code is as follows:

Class ChatServer (dispatcher): "" Chat Server "def _ init _ (self, port): dispatcher. _ init _ (self) self. create_socket (socket. AF_INET, socket. SOCK_STREAM) self. set_reuse_addr () self. bind ('', port) self. listen (5) self. users = {} self. main_room = ChatRoom (self) def handle_accept (self): conn, addr = self. accept () ChatSession (self, conn)
2. Session

With the server class, you also need to maintain the connection sessions of each user. Here we inherit the async_chat class of asynchat for implementation. The Code is as follows:

Class ChatSession (async_chat): "communicates with a single user" def _ init _ (self, server, sock): async_chat. _ init _ (self, sock) self. server = server self. set_terminator ('\ n') self. data = [] self. name = None self. enter (LoginRoom (server) def enter (self, room): 'remove itself from the current room and add it to the specified room.' try: cur = self. room failed t AttributeError: pass else: cur. remove (self) self. room = room. add (self) def collect_incoming_data (self, data): 'Accept client data' self. data. append (data) def found_terminator (self): 'processing when a piece of data on the client ends 'line = ''. join (self. data) self. data = [] try: self. room. handle (self, line) handle T EndSession: self. handle_close () def handle_close (self): async_chat.handle_close (self) self. enter (LogoutRoom (self. server ))
3. Command Interpreter

Now you need a command interpreter to interpret user commands, such as logging on to and querying online users and sending messages. The Code is as follows:

Class CommandHandler: "command processing class" def unknown (self, session, cmd): 'respond to unknown command' session. push ('unknown command: % s \ n' % cmd) def handle (self, session, line): 'COMMAND processing 'if not line. strip (): return parts = line. split ('', 1) cmd = parts [0] try: line = parts [1]. strip () handle T IndexError: line = ''meth = getattr (self, 'Do _ '+ cmd, None) try: meth (session, line) handle T TypeError: self. unknown (session, cmd)
4. Room

Next, we need to implement the room in the chat room. Here we define three rooms: the room where the user just logged on, the room for chatting, and the room for exiting the login, all three rooms have a public parent class. The Code is as follows:

Class Room (CommandHandler): "contains multiple user environments, responsible for basic command processing and broadcast" def _ init _ (self, server): self. server = server self. sessions = [] def add (self, session): 'One user enters the room' self. sessions. append (session) def remove (self, session): 'One user leaves the room' self. sessions. remove (session) def broadcast (self, line): 'send the specified message to all users'. 'for session in self. sessions: session. push (line) def do_logout (self, session, line): 'exit from the room' raise EndSessionclass LoginRoom (Room ): "New User's Room" def add (self, session): 'user connection successful response' Room. add (self, session) session. push ('connect Success ') def do_login (self, session, line): 'login command processing' name = line. strip () if not name: session. push ('username empty') elif name in self. server. users: session. push ('username exist') else: session. name = name session. enter (self. server. main_room) class ChatRoom (Room): "chat Room" def add (self, session): 'broadcast new user into 'session. push ('login Success ') self. broadcast (session. name + 'has entered the room. \ n') self. server. users [session. name] = session Room. add (self, session) def remove (self, session): 'broadcast user leaves 'room. remove (self, session) self. broadcast (session. name + 'has left the room. \ n') def do_say (self, session, line): 'client sends message' self. broadcast (session. name + ':' + line + '\ n') def do_look (self, session, line): 'view Online users' session. push ('Online Users: \ n') for other in self. sessions: session. push (other. name + '\ n') class LogoutRoom (Room): "Room when the user exits" def add (self, session): 'remove from server' try: del self. server. users [session. name] doesn t KeyError: pass
5. Complete server code
#! /Usr/bin/python # encoding: utf-8from asyncore import dispatcherfrom asynchat import async_chatimport socket, asyncorePORT = 6666 # Port class EndSession (Exception ): "Custom session end exceptions" passclass CommandHandler: "command processing class" def unknown (self, session, cmd ): 'respond to unknown command' session. push ('unknown command: % s \ n' % cmd) def handle (self, session, line): 'COMMAND processing 'if not line. strip (): return parts = line. split ('', 1) cmd = parts [0] try: line = parts [1]. strip () handle T IndexError: line = ''meth = getattr (self, 'Do _ '+ cmd, None) try: meth (session, line) handle T TypeError: self. unknown (session, cmd) class Room (CommandHandler): "contains multiple user environments, responsible for basic command processing and broadcasting "def _ init _ (self, server): self. server = server self. sessions = [] def add (self, session): 'One user enters the room' self. sessions. append (session) def remove (self, session): 'One user leaves the room' self. sessions. remove (session) def broadcast (self, line): 'send the specified message to all users'. 'for session in self. sessions: session. push (line) def do_logout (self, session, line): 'exit from the room' raise EndSessionclass LoginRoom (Room ): "New User's Room" def add (self, session): 'user connection successful response' Room. add (self, session) session. push ('connect Success ') def do_login (self, session, line): 'login command processing' name = line. strip () if not name: session. push ('username empty') elif name in self. server. users: session. push ('username exist') else: session. name = name session. enter (self. server. main_room) class ChatRoom (Room): "chat Room" def add (self, session): 'broadcast new user into 'session. push ('login Success ') self. broadcast (session. name + 'has entered the room. \ n') self. server. users [session. name] = session Room. add (self, session) def remove (self, session): 'broadcast user leaves 'room. remove (self, session) self. broadcast (session. name + 'has left the room. \ n') def do_say (self, session, line): 'client sends message' self. broadcast (session. name + ':' + line + '\ n') def do_look (self, session, line): 'view Online users' session. push ('Online Users: \ n') for other in self. sessions: session. push (other. name + '\ n') class LogoutRoom (Room): "Room when the user exits" def add (self, session): 'remove from server' try: del self. server. users [session. name] cipher t KeyError: passclass ChatSession (async_chat): "communicates with a single user" def _ init _ (self, server, sock): async_chat. _ init _ (self, sock) self. server = server self. set_terminator ('\ n') self. data = [] self. name = None self. enter (LoginRoom (server) def enter (self, room): 'remove itself from the current room and add it to the specified room.' try: cur = self. room failed t AttributeError: pass else: cur. remove (self) self. room = room. add (self) def collect_incoming_data (self, data): 'Accept client data' self. data. append (data) def found_terminator (self): 'processing when a piece of data on the client ends 'line = ''. join (self. data) self. data = [] try: self. room. handle (self, line) handle T EndSession: self. handle_close () def handle_close (self): async_chat.handle_close (self) self. enter (LogoutRoom (self. server) class ChatServer (dispatcher): "Chat server" def _ init _ (self, port): dispatcher. _ init _ (self) self. create_socket (socket. AF_INET, socket. SOCK_STREAM) self. set_reuse_addr () self. bind ('', port) self. listen (5) self. users = {} self. main_room = ChatRoom (self) def handle_accept (self): conn, addr = self. accept () ChatSession (self, conn) if _ name _ = '_ main _': s = ChatServer (PORT) try: asyncore. loop () Counter t KeyboardInterrupt: print
Iii. Project Practice (client)

After the server is complete, you need to implement the client. Here, the client connects to the server using the telnetlib module.

1. logon window

The graphical interface package here selects wxPython. The installation instructions are provided earlier. The logon window is implemented by inheriting the wx. Frame class. The Code is as follows:

Class LoginFrame (wx. frame): "Logon window" def _ init _ (self, parent, id, title, size): 'initialize, add controls, and bind the event' wx. frame. _ init _ (self, parent, id, title) self. setSize (size) self. center () self. serverAddressLabel = wx. staticText (self, label = "Server Address", pos = (10, 50), size = (120, 25) self. userNameLabel = wx. staticText (self, label = "UserName", pos = (40,100), size = (120, 25) self. serverAddress = Wx. textCtrl (self, pos = (120, 47), size = (150, 25) self. userName = wx. textCtrl (self, pos = (120, 97), size = (150, 25) self. loginButton = wx. button (self, label = 'login', pos = (80,145), size = (130, 30) self. loginButton. bind (wx. EVT_BUTTON, self. login) self. show () def login (self, event): 'logon process' try: serverAddress = self. serverAddress. getLineText (0 ). split (':') con. open (serverAddress [0], port = Int (serverAddress [1]), timeout = 10) response = con. read_some () if response! = 'Connect Success ': self. showDialog ('error', 'connect Fail! ', (95, 20) return con. write ('login' + str (self. userName. getLineText (0) + '\ n') response = con. read_some () if response = 'username empty': self. showDialog ('error', 'username Empty! ', (135, 20) elif response = 'username exist': self. showDialog ('error', 'username Exist! ', (135, 20) else: self. close () ChatFrame (None,-2, title = 'shiyanlou Chat client', size = (500,350) handle T Exception: self. showDialog ('error', 'connect Fail! ', (95, 20) def showDialog (self, title, content, size): 'display error message dialog box' dialog = wx. dialog (self, title = title, size = size) dialog. center () wx. staticText (dialog, label = content) dialog. showModal ()
2. Chat Window

In the chat window, the most important thing is to send a message to the server and receive the message from the server. Here, the subthread is used to accept the message. The Code is as follows:

Class ChatFrame (wx. frame): "chat window" def _ init _ (self, parent, id, title, size): 'initialize, add controls, and bind events 'wx. frame. _ init _ (self, parent, id, title) self. setSize (size) self. center () self. chatFrame = wx. textCtrl (self, pos = (5, 5), size = (490,310), style = wx. TE_MULTILINE | wx. TE_READONLY) self. message = wx. textCtrl (self, pos = (5,320), size = (300, 25) self. sendButton = wx. button (self, label = "Send ", Pos = (310,320), size = (58, 25) self. usersButton = wx. button (self, label = "Users", pos = (373,320), size = (58, 25) self. closeButton = wx. button (self, label = "Close", pos = (436,320), size = (58, 25) self. sendButton. bind (wx. EVT_BUTTON, self. send) self. usersButton. bind (wx. EVT_BUTTON, self. lookUsers) self. closeButton. bind (wx. EVT_BUTTON, self. close) thread. start_new_thread (self. receive ,() Self. Show () def send (self, event): 'send message' message = str (self. message. GetLineText (0). strip () if message! = '': Con. write ('say' + message + '\ n') self. message. clear () def lookUsers (self, event): 'view current online user' con. write ('look \ n') def close (self, event): 'close Windows' con. write ('logout \ n') con. close () self. close () def receive (self): 'Accept server message' while True: sleep (0.6) result = con. read_very_eager () if result! = '': Self. chatFrame. AppendText (result)
3. Complete client code
#! /Usr/bin/python # encoding: utf-8import wximport telnetlibfrom time import sleepimport threadclass LoginFrame (wx. frame): "Logon window" def _ init _ (self, parent, id, title, size): 'initialize, add controls, and bind the event' wx. frame. _ init _ (self, parent, id, title) self. setSize (size) self. center () self. serverAddressLabel = wx. staticText (self, label = "Server Address", pos = (10, 50), size = (120, 25) self. userNameLabel = wx. S TaticText (self, label = "UserName", pos = (40,100), size = (120, 25) self. serverAddress = wx. textCtrl (self, pos = (120, 47), size = (150, 25) self. userName = wx. textCtrl (self, pos = (120, 97), size = (150, 25) self. loginButton = wx. button (self, label = 'login', pos = (80,145), size = (130, 30) self. loginButton. bind (wx. EVT_BUTTON, self. login) self. show () def login (self, event): 'login process' try: se RverAddress = self. serverAddress. getLineText (0 ). split (':') con. open (serverAddress [0], port = int (serverAddress [1]), timeout = 10) response = con. read_some () if response! = 'Connect Success ': self. showDialog ('error', 'connect Fail! ', (95, 20) return con. write ('login' + str (self. userName. getLineText (0) + '\ n') response = con. read_some () if response = 'username empty': self. showDialog ('error', 'username Empty! ', (135, 20) elif response = 'username exist': self. showDialog ('error', 'username Exist! ', (135, 20) else: self. close () ChatFrame (None,-2, title = 'shiyanlou Chat client', size = (500,350) handle T Exception: self. showDialog ('error', 'connect Fail! ', (95, 20) def showDialog (self, title, content, size): 'display error message dialog box' dialog = wx. dialog (self, title = title, size = size) dialog. center () wx. staticText (dialog, label = content) dialog. showModal () class ChatFrame (wx. frame): "chat window" def _ init _ (self, parent, id, title, size): 'initialize, add controls, and bind events 'wx. frame. _ init _ (self, parent, id, title) self. setSize (size) self. center () self. chatFrame = wx. textCtrl (Self, pos = (5, 5), size = (490,310), style = wx. TE_MULTILINE | wx. TE_READONLY) self. message = wx. textCtrl (self, pos = (5,320), size = (300, 25) self. sendButton = wx. button (self, label = "Send", pos = (310,320), size = (58, 25) self. usersButton = wx. button (self, label = "Users", pos = (373,320), size = (58, 25) self. closeButton = wx. button (self, label = "Close", pos = (436,320), size = (58, 25) self. sendButton. bind (wx. EVT_BUTTON, self. send) self. usersButton. bind (wx. EVT_BUTTON, self. lookUsers) self. closeButton. bind (wx. EVT_BUTTON, self. close) thread. start_new_thread (self. receive, () self. show () def send (self, event): 'send message' message = str (self. message. getLineText (0 )). strip () if message! = '': Con. write ('say' + message + '\ n') self. message. clear () def lookUsers (self, event): 'view current online user' con. write ('look \ n') def close (self, event): 'close Windows' con. write ('logout \ n') con. close () self. close () def receive (self): 'Accept server message' while True: sleep (0.6) result = con. read_very_eager () if result! = '': Self. chatFrame. appendText (result) 'running' if _ name _ = '_ main _': app = wx. app () con = telnetlib. telnet () LoginFrame (None,-1, title = "Login", size = (280,200) app. mainLoop ()
Iv. Summary

Finally, you can run the program to chat. Note that you must first start the server and then start the client. This project uses asyncore's dispatcher to implement servers. asynchat's asyn_chat is used to maintain user connection sessions. wxPython is used to implement graphical interfaces and telnetlib is used to connect to servers, in the child thread, a simple chat room program is completed by receiving messages from the server.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.