-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathGserver.py
More file actions
172 lines (143 loc) · 5.87 KB
/
Gserver.py
File metadata and controls
172 lines (143 loc) · 5.87 KB
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
#! /usr/bin/env python
# encoding:utf-8
"""
@author: DYS
@file: Gserver.py
@time: 2018/4/20 13:40
"""
import socket
from db import DB
from threading import currentThread, Thread
class HandlerThread(object):
queue = [] # sockect 队列
db = DB()
def __init__(self, sock):
self.sock = sock
def recv(self):
data = self.sock.recv(1024).strip() # 如果使用 while 接收数据时,会导致用户必须多敲一次回车键
return data.decode('utf-8')
def send(self, data):
# self.sock.sendall(('[System]: %s' % data).encode('utf-8'))
self.sock.send(data.encode('utf-8')) # send传的是bytes,所以要要encode编码一下
# 向队列中广播消息
def broadcast(self, user, data):
for sock in self.queue:
sock.sendall('\n[%s]: %s\n' % (user, data))
# 关闭客户端连接
def stop(self):
self.send('ByeBye!')
self.sock.close()
self.queue.remove(self.sock) # 关闭连接后,记得从队列中删除
# 程序入口
def handler(self):
funcdict = {
'login': self.login,
'register': self.register
}
try:
thname = currentThread().getName()
print('[%s] Got connection from %s' % (thname, self.sock.getpeername())) # 该程序中所有 print 的数据,将全部使用 loging 模块代替
self.send('请输入你要选择的功能:login/register/exit')
data = self.recv()
# print("data:", data)
if data == 'exit':
self.stop() # 其实这里应该单独使用 self.sock.close() 来关闭连接,因为这时队列中并没有该连接,不过有了下面的捕获就没有问题了 ^_^
elif data in funcdict:
# print("jinalile...")
return funcdict.get(data)()
else:
self.handler()
except Exception as e: # 如果这里不捕获一下,就无法正常断开客户端连接
print("发生异常!!!异常信息为:", e)
# 处理用户登陆
def login(self):
self.send('Login... 请输入用户名密码,格式:User Password,输入 Server: 执行程序指令!')
user_data = self.recv()
# 程序内部指令
if user_data == 'Server:':
self.send('\n\tServer:use reged\t切换到注册页\n\tServer:exit\t\t退出系统')
user_data = self.recv()
if user_data == 'Server:use reged':
self.register()
elif user_data == 'Server:exit':
self.stop()
else:
self.send('输入错误...')
datalist = user_data.split()
# 判断用户输入,格式是否正确
if len(datalist) == 2:
user = datalist[0]
password = datalist[1]
db_data = self.db.get_data() or {}
if user in db_data and password == db_data.get(user):
self.queue.append(self.sock) # 有权限登陆系统者,连接被加入到队列中
self.send('欢迎加入聊天室,输入 Server: 获取功能方法!')
self.broadcast('System', '[%s] 加入聊天室!' % user)
self.chat_room(user)
else:
self.send('用户名、密码错误!')
self.login()
self.login()
def register(self):
self.send('Register... 请输入用户名密码,格式:User Password,输入 Server: 执行程序指令!')
user_data = self.recv()
if user_data == 'Server:':
self.send('\n\tServer:use login\t切换到注册页\n\tServer:exit\t\t退出系统')
user_data = self.recv()
if user_data == 'Server:login':
self.login()
elif user_data == 'Server:exit':
self.stop()
else:
self.send('输入错误...')
datalist = user_data.split()
if len(datalist) == 2:
user = datalist[0]
password = datalist[1]
db_data = self.db.get_data() or {}
if user in db_data:
self.send('该用户名已被注册!')
self.register()
else:
db_data[user] = password
self.db.put_data(db_data)
self.queue.append(self.sock)
self.broadcast('System', '新用户 [%s] 加入聊天室!' % user)
self.chat_room(user)
self.register()
def chat_room(self, user):
user_data = self.recv()
if user_data == 'Server:':
self.send('\n\tServer:logout\t退出聊天室')
user_data = self.recv()
if user_data == 'Server:logout':
self.stop()
return # 这里如果不加 return ,会将客户端执行的 Server: 指令也广播出去
else:
self.send('输入错误...')
self.chat_room(user)
else:
self.broadcast(user, user_data)
self.chat_room(user)
# 为每连接创建线程
def Startthread(sock, addr):
print('Received new client connection. %s:%s' % (addr[0], addr[1]))
th = HandlerThread(sock)
t = Thread(target=th.handler)
t.setDaemon(True)
t.start()
# 启动服务
def Server():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 17170))
s.listen(5)
while True:
try:
sock, addr = s.accept()
except KeyboardInterrupt:
exit('\nByeBye!')
Startthread(sock, addr)
s.close()
if __name__ == '__main__':
Server()