-
Notifications
You must be signed in to change notification settings - Fork 0
/
chatserver.py
234 lines (190 loc) · 5.61 KB
/
chatserver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
from asyncore import dispatcher
from asynchat import async_chat
import socket,asyncore
PORT=5005
NAME='TestChat'
'''
available commands:
command format function
login login<name> login to the main room with the name
say say<something> send a message in the specified room
look look check the online people's list in the room
userls userls check the online people's list in the server
talkto talkto<name> create a new room that contains you and the person named 'name'
back back go back to main chat room
logout logout logout the user, exit the program
roomls roomls check the total chat room list on the server
create create<room name> create a new chat room for communication
'''
class EndSession(Exception):pass
class MyHandle():
'''
get user's first input word as a command
'''
def unmatched(self,session,cmd):
session.push("No such command %s found\r\n" %cmd)
def handle(self,session,line):
if not line.strip():
return
parts = line.split(' ',1)
cmd = parts[0]
try:
line=parts[1].strip()
except IndexError:
line=''
func=getattr(self, 'do_'+cmd,None)
try:
func(session,line)
except TypeError:
self.unmatched(session, cmd)
class Room(MyHandle):
'''
base type
'''
def __init__(self,server):
self.server=server
self.sessions=[]
def add(self,session):
self.sessions.append(session)
def remove(self,session):
if session in self.sessions:
self.sessions.remove(session)
def broadcast(self,line):
for session in self.sessions:
session.push(line)
def do_logout(self,session,line):
raise EndSession
class LoginRoom(Room):
'''
single user room for login
'''
def __init__(self,server):
Room.__init__(self, server)
def add(self,session):
Room.add(self, session)
session.push('Welcome to %s\r\n' %self.server.name)
def unmatched(self,session,line):
'''
you can only do login in LoginRoom
'''
session.push('Please login first \nUse command login<name>\r\n')
def do_login(self,session,line):
name=line.strip()
if not name:
session.push('please enter a nick name first:\r\n')
elif name in self.server.userDict:
session.push('Name is already taken')
session.push('Please try again')
else:
session.name=name
session.enter(self.server.mainRoom)
class LogoutRoom(Room):
def __init__(self,server):
Room.__init__(self, server)
def add(self,session):
'''
do remove the session here
'''
self.logout(session)
def logout(self,session):
if session.name in self.server.userDict.keys():
del self.server.userDict[session.name]
print 'client disconnect------',session.name
class ChatRoom(Room):
def __init__(self,server,name=''):
Room.__init__(self, server)
self.name=name
self.server.roomDict[self.name]=self
def add(self,session):
Room.add(self, session)
self.broadcast('%s has entered the %s room.\r\n' %(session.name,self.name))
self.server.userDict[session.name]=session
def remove(self,session):
Room.remove(self, session)
self.broadcast('%s has left the room.\r\n' %session.name)
def do_say(self,session,line):
self.broadcast(session.name+': '+line+'\r\n')
def do_look(self,session,line):
session.push('the following users are in the room\r\n')
for user in self.sessions:
session.push(user.name+'\r\n')
session.push('------------------\r\n')
def do_userls(self,session,line):
session.push('the following users are in the server\r\n')
for username in self.server.userDict:
session.push(username+'\r\n')
session.push('------------------\r\n')
def do_chatto(self,session,line):
line=line.strip()
if line in self.server.userDict.keys():
session2=self.server.userDict[line]
newRoom=PrivateRoom(self.server)
session.enter(newRoom)
session2.enter(newRoom)
else:
session.push("Connection failed\r\n")
session.push("Please make sure you enter the right name and try again\r\n")
def do_roomls(self,session,line):
session.push('the following rooms are in the server\r\n')
for roomname in self.server.roomDict:
session.push(roomname+'\r\n')
session.push('------------------\r\n')
class PrivateRoom(ChatRoom):
'''
when a user exit the room, the room destroyed
'''
def __init__(self,server,name='private'):
ChatRoom.__init__(self, server,name)
def do_back(self,session,line):
session.enter(self.server.mainRoom)
class ChatSession(async_chat):
'''
handle the connection
between the server and a client
'''
def __init__(self,server,sock):
async_chat.__init__(self,sock)
self.server=server
self.set_terminator("\r\n")
self.data=[]
self.name='Anonymous'
self.room=None
self.enter(LoginRoom(server))
def enter(self,room):
currentRoom=self.room
if currentRoom!=None:
currentRoom.remove(self)
self.room=room
room.add(self)
def collect_incoming_data(self,data):
self.data.append(data)
def found_terminator(self):
line=''.join(self.data)
self.data=[]
try:
self.room.handle(self,line)
except EndSession:
self.handle_close()
def handle_close(self):
async_chat.handle_close(self)
self.enter(LogoutRoom(self.server))
class ChatServer(dispatcher):
def __init__(self,port,name):
dispatcher.__init__(self)
self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(('',port))
self.listen(5)
self.name=name
self.userDict={}
self.roomDict={}
self.mainRoom=ChatRoom(self,'MAIN')
def handle_accept(self):
conn, addr = self.accept()
self.name=addr[0]
print 'client connected------',addr
ChatSession(self,conn)
if __name__=='__main__':
s=ChatServer(PORT,NAME)
try:asyncore.loop()
except KeyboardInterrupt: print