-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
387 lines (357 loc) · 13.2 KB
/
Copy pathserver.py
File metadata and controls
387 lines (357 loc) · 13.2 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
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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
import pymysql
import sys
if(sys.version[:1] == "3"):
import _thread as thread
import time
# import thread
import socket
#来自客户端的请求列表
def req_handler(params, connection):
switcher = {
'req_login': req_login,
'req_sign': req_sign,
'req_refresh_list': req_refresh_list,
'req_change_nick': req_change_nick,
'req_send_text': req_send_text,
'req_acquire_chatrecord': req_acquire_chatrecord,
'req_acquire_more_chatrecord': req_acquire_more_chatrecord,
'req_send_pyq': req_send_pyq,
'req_comment_pyq': req_comment_pyq,
'req_acquire_pyq': req_acquire_pyq,
'req_pyq_good': req_pyq_good,
}
try:
func = switcher.get(params[0], lambda:"nothing")
except Exception:
print('proto error!')
return
return func(params, connection)
#以下为各种变量的定义
#id_conn: id对conn, nick的映射
#conn_id: conn对id, nick的映射,与id_conn组成在线列表
#user_list: 所有成员,包括在线和不在线的列表 映射关系 id : nick
#conn 为本地mysql的连接
id_conn = {}
conn_id = {}
user_list = {}
sqlconn = pymysql.connect(user = 'root', password = '123', database = 'socket_project', charset = 'utf8')
cursor = sqlconn.cursor()
#以下为服务器内部操作的接口
def init_user_list():
sql = "select * from users;"
cursor.execute(sql)
result = cursor.fetchall()
for id, password, nick in result:
user_list[id] = nick
#以下为各种客户端请求的协议------------------------------------------------------------------------
def req_login(params, conn):
id = params[1]
password = params[2]
if id in id_conn:
data = '||'.join(['ack_login', 'not'])
conn.send(data.encode('utf-8'))
return
sql = "select * from users where id = '%s' and pass = '%s';"%(id, password)
try:
cursor.execute(sql)
except Exception:
print('sql error!')
return
result = cursor.fetchall()
if(len(result) > 0):
nick = result[0][2]
data = '||'.join(['ack_login', 'ok', id, nick])
id_conn[id] = (conn, nick)
conn_id[conn] = (id, nick)
conn.send(data.encode('utf-8'))
else:
data = '||'.join(['ack_login', 'not'])
conn.send(data.encode('utf-8'))
def req_sign(params, conn):
id = params[1]
password = params[2]
nick = params[3]
sql = "select * from users where id = '%s';"%id
try:
cursor.execute(sql)
except Exception:
print('sql error!')
return
result = cursor.fetchall()
if(len(result) > 0):
data = '||'.join(['ack_sign', 'not'])
conn.send(data.encode('utf-8'))
else:
sql = "insert into users values('%s', '%s', '%s');"%(id, password, nick)
cursor.execute(sql)
sqlconn.commit()
user_list[id] = nick
data = '||'.join(['ack_sign', 'ok'])
conn.send(data.encode('utf-8'))
#发送的格式:id, nickname, is_online
def req_refresh_list(params, conn):
ret_list = []
for id, nick in user_list.items():
if id in id_conn:
data = '##'.join([id, nick, 'yes'])
else:
data = '##'.join([id, nick, 'no'])
ret_list.append(data)
ret_data = '||'.join(ret_list)
ret_data = '||'.join(['ack_refresh_list', ret_data])
conn.send(ret_data.encode('utf-8'))
#修改昵称
def req_change_nick(params, conn):
id = params[1]
new_nick = params[2]
id_conn[id] = (conn, new_nick)
conn_id[conn] = (id, new_nick)
user_list[id] = new_nick
sql = "update users set nick_name = '%s' where id = '%s';"%(new_nick, id)
try:
cursor.execute(sql)
except Exception:
print('sql error!')
sqlconn.commit()
ret_data = '||'.join(['ack_change_nick', new_nick])
conn.send(ret_data.encode('utf-8'))
def req_send_text(params, conn):
sender_id = params[1]
recver_id = params[2]
text = params[3]
dt = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
retdata = '||'.join(['ack_send_text', sender_id, user_list[sender_id], recver_id, text, dt])
#私聊
if recver_id != '0':
sql = "insert into chat_records values('%s', '%s', '%s', '%s');"%(sender_id, recver_id, dt, text)
try:
cursor.execute(sql)
except Exception:
print('sql error!')
return
sqlconn.commit()
if sender_id in id_conn:
id_conn[sender_id][0].send(retdata.encode('utf-8'))
if recver_id in id_conn:
id_conn[recver_id][0].send(retdata.encode('utf-8'))
else: #聊天大厅
sql = "insert into chat_global values('%s', '%s', '%s');"%(sender_id, dt, text)
try:
cursor.execute(sql)
except Exception:
print('sql error!')
return
sqlconn.commit()
for conn, values in conn_id.items():
conn.send(retdata.encode('utf-8'))
#params: sender, recver
#retdata : recver_id + (senderid, sendernick, time, text),(),.....
def req_acquire_chatrecord(params, conn):
sender_id = params[1]
recver_id = params[2]
if(recver_id == '0'): #请求聊天大厅的记录
sql = "select * from chat_global;"
cursor.execute(sql)
data = cursor.fetchall()
tmp = []
l = len(data)
if l < 20:
for sid, t, text in data:
t_str = t.strftime("%Y-%m-%d %H:%M:%S")
tmp.append('##'.join([sid, user_list[sid], t_str, text]))
else:
for i in range(l - 20, l):
sid = data[i][0]
t = data[i][1]
text = data[i][2]
t_str = t.strftime("%Y-%m-%d %H:%M:%S")
tmp.append('##'.join([sid, user_list[sid], t_str, text]))
tmp2 = '||'.join(tmp)
ret_data = '||'.join(['ack_acquire_chatrecord', recver_id, tmp2])
conn.send(ret_data.encode('utf-8'))
else:
sql = "select * from chat_records where (sender_id = '%s' and recver_id = '%s') or (sender_id = '%s' and recver_id = '%s') order by send_time"\
%(sender_id, recver_id, recver_id, sender_id)
cursor.execute(sql)
data = cursor.fetchall()
tmp = []
l = len(data)
if l < 20:
for sid, rid, t, text in data:
t_str = t.strftime("%Y-%m-%d %H:%M:%S")
tmp.append('##'.join([sid, user_list[sid], t_str, text]))
else:
for i in range(l - 20, l):
sid = data[i][0]
t = data[i][2]
text = data[i][3]
t_str = t.strftime("%Y-%m-%d %H:%M:%S")
tmp.append('##'.join([sid, user_list[sid], t_str, text]))
tmp2 = '||'.join(tmp)
ret_data = '||'.join(['ack_acquire_chatrecord', recver_id, tmp2])
conn.send(ret_data.encode('utf-8'))
def req_acquire_more_chatrecord(params, conn):
sender_id = params[1]
recver_id = params[2]
if (recver_id == '0'): # 请求聊天大厅的记录
sql = "select * from chat_global;"
cursor.execute(sql)
data = cursor.fetchall()
tmp = []
l = len(data)
if l < 80:
for sid, t, text in data:
t_str = t.strftime("%Y-%m-%d %H:%M:%S")
tmp.append('##'.join([sid, user_list[sid], t_str, text]))
else:
for i in range(l - 80, l):
sid = data[i][0]
t = data[i][1]
text = data[i][2]
t_str = t.strftime("%Y-%m-%d %H:%M:%S")
tmp.append('##'.join([sid, user_list[sid], t_str, text]))
tmp2 = '||'.join(tmp)
ret_data = '||'.join(['ack_acquire_chatrecord', recver_id, tmp2])
conn.send(ret_data.encode('utf-8'))
else:
sql = "select * from chat_records where (sender_id = '%s' and recver_id = '%s') or (sender_id = '%s' and recver_id = '%s') order by send_time"\
%(sender_id, recver_id, recver_id, sender_id)
cursor.execute(sql)
data = cursor.fetchall()
tmp = []
l = len(data)
if l < 80:
for sid, rid, t, text in data:
t_str = t.strftime("%Y-%m-%d %H:%M:%S")
tmp.append('##'.join([sid, user_list[sid], t_str, text]))
else:
for i in range(l - 80, l):
sid = data[i][0]
t = data[i][2]
text = data[i][3]
t_str = t.strftime("%Y-%m-%d %H:%M:%S")
tmp.append('##'.join([sid, user_list[sid], t_str, text]))
tmp2 = '||'.join(tmp)
ret_data = '||'.join(['ack_acquire_chatrecord', recver_id, tmp2])
conn.send(ret_data.encode('utf-8'))
#发朋友圈
def req_send_pyq(params, conn):
sender_id = params[1]
send_time = params[2]
context = params[3]
sql = "insert into pyq_main values('%s', '%s', '%s', 0);"%(sender_id, send_time, context)
try:
cursor.execute(sql)
except Exception:
print('send pyq failed!')
return
sqlconn.commit()
#评论朋友圈
def req_comment_pyq(params, conn):
sender_id = params[1]
send_time = params[2]
commenter_id = params[3]
context = params[4]
sql = "insert into pyq_comment values('%s', '%s', '%s', '%s')"%(sender_id, send_time, commenter_id, context)
try:
cursor.execute(sql)
except Exception:
print('send pyq comment failed!')
return
sqlconn.commit()
#如果对方在线通知对方客户端
if sender_id in id_conn:
conn_sender = id_conn[sender_id][0]
if conn_sender != conn:
conn_sender.send('ack_pyq_gooded'.encode('utf-8'))
#获取/刷新朋友圈
def req_acquire_pyq(params, conn):
acker_id = params[1]
if acker_id == '0':
sql = "select * from pyq_main order by send_time;"
else:
sql = "select * from pyq_main where sender_id = '%s' order by send_time"%acker_id
try:
cursor.execute(sql)
except Exception:
print('db error!')
return
result= cursor.fetchall()
pyqs = []
i = 0
for id, dt, content, counter in result:
if i >= 25:
break
send_time = dt.strftime("%Y-%m-%d %H:%M:%S")
nick = user_list[id]
#搜索这条朋友圈的评论
comments = []
sql = "select * from pyq_comment where sender_id = '%s' and send_time = '%s';"%(id, send_time)
cursor.execute(sql)
result_2 = cursor.fetchall()
for id_cmt, dt_cmt, commenter_id, comment in result_2:
nick_cmt = user_list[commenter_id]
comments.append(nick_cmt + '&&' + comment)
comments_str = '**'.join(comments)
#data = nick ^^ id ^^ send_time ^^ counter ^^ content ^^ nick1 && cmt1 ** nick2 && cmt2
one_pyq = [nick, id, send_time, str(counter), content, comments_str]
pyqs.append('^^'.join(one_pyq))
i = i + 1
#data_all = data1 || data2 || ...
data = '||'.join(pyqs)
retdata = '||'.join(['ack_acquire_pyq', data])
conn.send(retdata.encode('utf-8'))
#点赞
def req_pyq_good(params, conn):
sender_id = params[1]
send_time = params[2]
sql = "update pyq_main set cool_counter = cool_counter + 1 where sender_id = '%s' and send_time = '%s';"%(sender_id, send_time)
try:
cursor.execute(sql)
except Exception:
print('点赞错误!')
return
sqlconn.commit()
if sender_id in id_conn:
conn_sender = id_conn[sender_id][0]
if conn_sender != conn:
conn_sender.send('ack_pyq_gooded'.encode('utf-8'))
##----------------------------------------------------------------------------------------------
def child_connection(index, sock, connection, address):
try:
print("begin connecion %d" % index)
# 获得一个连接,然后开始循环处理这个连接发送的信息
while True:
buf = connection.recv(1024).decode('utf-8')
params = buf.split('||')
req_handler(params, connection)
except Exception: # 如果建立连接后,该连接在设定的时间内无数据发来,则time out
print("closing connection %d" % index) # 当一个连接监听循环退出后,连接可以关掉
connection.close()
if connection in conn_id:
id = conn_id[connection][0]
if id in id_conn:
id_conn.pop(id)
conn_id.pop(connection)
# 关闭连接,最后别忘了退出线程
thread.exit_thread()
'''
建立一个python server,监听指定端口,
如果该端口被远程连接访问,则获取远程连接,然后接收数据,
并且做出相应反馈。
'''
if __name__ == "__main__":
print("Server is starting")
init_user_list()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('10.222.201.44', 8998)) # 配置soket,绑定IP地址和端口号
sock.listen(5) # 设置最大允许连接数,各连接和server的通信遵循FIFO原则
index = 0
while True: # 循环轮询socket状态,等待访问
connection, address = sock.accept()
index += 1
# 当获取一个新连接时,启动一个新线程来处理这个连接
thread.start_new_thread(child_connection, (index, sock, connection, address))
if index > 100:
break
sock.close()