-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathServer.py
159 lines (133 loc) · 5.68 KB
/
Server.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
import socket
import threading
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('0.0.0.0', 5963))
sock.listen(10)
print('Server', socket.gethostbyname('0.0.0.0'), 'listening ...')
myDict = dict() # 当前在线人员昵称列表
myList = list() # 当前socket在线客户端列表
# 向除自己外的所有人发送消息
def tellOthers(exceptNum, whatToSay):
for othersClient in myList:
if othersClient.fileno() != exceptNum:
try:
othersClient.send((whatToSay + '\n').encode())
except Exception as mException:
print('22 exception is : %s' % mException)
# 向自己发送消息
def tellMySelf(exceptNum, whatToSay):
for myClient in myList:
if myClient.fileno() == exceptNum:
try:
myClient.send((whatToSay + '\n').encode())
except Exception as e:
print('32 exception is : %s' % e)
# 向所有人发送服务器公告
def notificationAll(bulletin):
whatToSend = '[proclamation]:[%s]' % bulletin
for allClient in myList:
try:
allClient.send((whatToSend + '\n').encode())
except Exception as e:
print('41 exception is : %s' % e)
# 判断名字是否存在 不存在则返回True
def isName(nickName):
nameList = list(myDict.values())
if nickName not in nameList and nickName.split():
print('48 传入的值为 %s 列表为 %s' % (nickName, nameList))
return True # 不在列表中返回True
return False
# 向所有人发送当前在线人数
def sendAll():
online = str(len(myDict))
onlineSend = '[decide]:[%s]' % online
for allClient in myList:
try:
allClient.send((onlineSend + '\n').encode())
except Exception as e:
print('61 exception is : %s' % e)
def subThreadIn(myConnection, connNumber):
nickname = ''
disconnect = False
mContinue = True
while True:
try:
nickname = myConnection.recv(1024).decode()
except IOError as mIOError:
print('72 recv exceptional %s' % mIOError)
if nickname == 'disconnect':
myConnection.send('disconnect\n'.encode()) # 发送终止链接指令
mContinue = False
myConnection.close()
print('77 close the connection %s' % myConnection)
break
else:
if isName(nickname):
myDict[connNumber] = nickname # 将初始化昵称加入至在线人列表
myList.append(myConnection) # 将连接加入在线客户端列表
myConnection.send('[correct]:[success]\n'.encode()) # 发送链接成功
break
else:
myConnection.send('[correct]:[failure]\n'.encode()) # 发送链接失败
continue
if mContinue:
print('90 connection', connNumber, ' has nickname :', nickname)
# 向其他人发送自己加入房间
tellOthers(connNumber, '[enter]:[' + myDict[connNumber] + ']')
# 向自己发送当前在线人员
tellMySelf(connNumber, '[Tip]:%s' % list(myDict.values()))
sendAll()
while True:
if disconnect:
tellMySelf(connNumber, 'disconnect') # 向自己发送断开连接指令
leave(myConnection, connNumber) # 告诉其他人我已离开
sendAll()
return
else:
try:
recvedMsg = myConnection.recv(1024).decode() # 阻塞接收消息
if recvedMsg == 'disconnect' or not recvedMsg.strip(): # 如果收到'disconnect' 则将退出位置True
disconnect = True
else:
print('108', myDict[connNumber], ':', recvedMsg) # 输出接收到的消息
tellOthers(connNumber, '[Msg]:[' + myDict[connNumber] + ',' + recvedMsg + ']')
except (OSError, ConnectionResetError):
leave(myConnection, connNumber) # 客户端直接退出时执行异常连接断开
return
# 离开函数
def leave(myConnection, connNumber):
try:
myList.remove(myConnection) # 从在线客户端列表中删除自己
except ValueError as mValueError:
print('121 mValueError is : %s' % mValueError)
print('122', myDict[connNumber], 'exit, ', len(myList), ' person left')
tellOthers(connNumber, '[Dis]:[' + myDict[connNumber] + ']') # 告诉其他人自己离开
myDict.pop(connNumber) # 从在线人员昵称列表中删除自己
myConnection.close() # 关闭连接
# 发布服务器通知
def notification():
while True:
notificationMsg = input()
notificationAll(notificationMsg)
# 启动一个系统通知线程
sendThread = threading.Thread(target=notification)
sendThread.start()
# 循环等待客户端接入
while True:
connection, address = sock.accept() # 阻塞接入客户端
print('142 Accept a new connection', connection, connection.getsockname(), connection.fileno(), address)
try:
# connection.settimeout(5)
buf = connection.recv(1024).decode()
if buf == '1':
connection.send('[wel]:[welcome]\n'.encode())
connection.send(('[decide]:[' + str(len(myList)) + ']\n').encode())
# 为当前连接开辟一个新的线程
myThread = threading.Thread(target=subThreadIn, args=(connection, connection.fileno()))
myThread.setDaemon(True)
myThread.start()
else:
connection.send('please go out!'.encode())
connection.close()
except Exception as exception:
print('159 exception is : %s' % exception)