正经的全班同学相似体型的计算

场景

在班级机房中, 每个人开一个服务器进程, 当收到客户端发过来的get请求时候, 返回自己的学号, 身高, 体重, 穿衣服尺码. 每个人写一个客户端, (机房IP地址是连续的40个)爬取同学们的信息, 然后本地计算哪两位同学体型最相似。

实现

在上一次的Python Socket编程实现服务端与客户端通讯中已经实现了服务端与客户端间的简单通讯,现在来实现场景中的功能。

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
import socket
import threading
import json

HOST = '127.0.0.1'
PORT = 1024

msg = {'id':'1527406014','height':178,'weight':60,'size':'XXL'}

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)

print('Server start at: %s:%s' %(HOST,PORT))
print('wait for connection...')

def link(connection,address):
print('Connected by ',address)

while True:
data = connection.recv(1024)
data = data.decode('utf-8')
if data == 'exit':
break
elif data == 'get':
connection.send(json.dumps(msg).encode('utf-8'))
print('send msg to ',address)
else:
connection.send('Server received you message.'.encode('utf-8'))

connection.shutdown(2)
connection.close()
print('close the connection with ',address)


while True:
connection, address = s.accept()
thread = threading.Thread(target = link,args = (connection,address))
thread.start()

client.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
import socket
import json
import tkinter as tk

def get_msg(msgs):
while True:
act = input('do something? :')

if act == 'exit':
s.send(act.encode('utf'))
break
elif act == 'get':
s.send(act.encode('utf-8'))
data = s.recv(1024)
data = json.loads(data.decode('utf-8'))
print('The massage of he is: ',data)
else:
pass

def trans_size(msg):
if msg['size'] == 'S':
msg['size'] = 0
elif msg['size'] == 'M':
msg['size'] = 1
elif msg['size'] == 'L':
msg['size'] = 2
elif msg['size'] == 'XL':
msg['size'] =3
elif msg['size'] == 'XXl':
msg['size'] =4
elif msg['size'] == 'XXXL':
msg['size'] = 5

def compare(result,msgs):
length = len(msgs)
for msg in msgs:
trans_size(msg)
i=0
while i<length :
j=i+1
while j<length:
t = abs(msgs[i]['height'] - msgs[j]['height']) + abs(msgs[i]['weight'] - msgs[j]['weight'])
+ abs(msgs[i]['size'] - msgs[j]['size'])
result.append({'id1': msgs[i]['id'],'id2': msgs[j]['id'],'result': t})
j = j + 1
i = i + 1
tmp = result[0]
for s in result:
if s['result'] < tmp['result']:
tmp = s
id_1 = str(tmp['id1'])
id_2 = str(tmp['id2'])
res = 'Gay1:' + id_1 + ' Gay2: ' + id_2
return res


def show_window(res):
window = tk.Tk()
window.title('在一起')
window.geometry('600x400')
var = tk.StringVar()
l = tk.Label(window, textvariable=var, bg='green', font=('Arial', 12), width=60, height=5)
l.pack()
on_hit = False
def hit_me():
var.set(res)
b = tk.Button(window, text='Who are the couple!', width=35,
height=2, command=hit_me)
b.pack()
window.mainloop()

if __name__ == '__main__':
HOST = '127.0.0.1'
PORT = 1024
stu_b = {
'id': 1527406003,
'height': 174,
'weight': 73,
'size': 'XL'
};
stu_c = {
'id': 1527406007,
'height': 140,
'weight': 51,
'size': 'M'
};
msgs = [stu_b, stu_c];
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
get_msg(msgs)
result = list()
gays = compare(result,msgs)
show_window(gays)

在这里约定了客户端在连接上服务端时服务端不会立即发送数据,而是在客户端给服务器端发送了get关键词后才发送数据,在客户端发送exit后连接关闭。

note

在开始的测试中发现在客户端发送exit后连接并没有正常的关闭,goole后发现close方法可以释放一个连接的资源,但是不是立即释放,如果想立即释放,那么在close之前使用shutdown方法。

shutdown方法是用来实现通信模式的,模式分三种,SHUT_RD 关闭接收消息通道,SHUT_WR 关闭发送消息通道,SHUT_RDWR 两个通道都关闭。也就是说,想要关闭一个连接,首先把通道全部关闭,然后在release连接,以上三个静态变量分别对应数字常量:0,1,2。