Skip to content

Commit 06546e8

Browse files
committed
python meta code
1 parent 4d700bd commit 06546e8

File tree

4 files changed

+310
-0
lines changed

4 files changed

+310
-0
lines changed

taiyangxue/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Python 代码实例
22

3+
- [meta](https://github.com/JustDoPython/python-examples/tree/master/taiyangxue/meta) : 几行代码,撸了个 元宇宙?!
34
- [fake-thread](https://github.com/JustDoPython/python-examples/tree/master/taiyangxue/fake-thread) : Python 多线程居然是 —— 假的?
45
- [logging-train](https://github.com/JustDoPython/python-examples/tree/master/taiyangxue/logging-train) : 神器 logging,你真的了解吗?
56
- [split-video](https://github.com/JustDoPython/python-examples/tree/master/taiyangxue/split-video) : 神器 ffmpeg —— 实现短视频批量化操作

taiyangxue/meta/metaClient.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import socket
2+
from threading import Thread
3+
4+
close = False
5+
6+
class bcolors:
7+
HEADER = '\033[95m'
8+
OKBLUE = '\033[94m'
9+
OKCYAN = '\033[96m'
10+
OKGREEN = '\033[92m'
11+
WARNING = '\033[93m'
12+
FAIL = '\033[91m'
13+
ENDC = '\033[0m'
14+
BOLD = '\033[1m'
15+
UNDERLINE = '\033[4m'
16+
17+
def receive(client):
18+
while True:
19+
try:
20+
s_info = client.recv(1024) # 接受服务端的消息并解码
21+
if not s_info:
22+
print(f"{bcolors.WARNING}服务器链接断开{bcolors.ENDC}")
23+
break
24+
print(f"{bcolors.OKCYAN}新的消息:{bcolors.ENDC}\n", bcolors.OKGREEN + s_info.decode('utf-8')+ bcolors.ENDC)
25+
except Exception:
26+
print(f"{bcolors.WARNING}服务器链接断开{bcolors.ENDC}")
27+
break
28+
if close:
29+
break
30+
31+
def createClient(ip, port):
32+
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
33+
client.connect((ip, port))
34+
return client
35+
36+
def help():
37+
print(":start\t启动")
38+
print(":stop\t关闭")
39+
print(':quit\t退出')
40+
print(':help\t帮助\n--------------')
41+
42+
if __name__ == '__main__':
43+
# 获取本机计算机名称
44+
hostname = socket.gethostname()
45+
# 获取本机ip
46+
# ip = '20.2.100.200' #socket.gethostbyname(hostname)
47+
ip = socket.gethostbyname(hostname)
48+
49+
client = None
50+
51+
thread = None
52+
help()
53+
while True:
54+
pass
55+
value = input("")
56+
value = value.strip()
57+
58+
if value == ':start':
59+
if thread:
60+
print(f"{bcolors.OKBLUE}您已经在元宇宙中了{bcolors.ENDC}")
61+
else:
62+
client = createClient(ip, 6000)
63+
thread = Thread(target=receive, args=(client,))
64+
thread.start()
65+
print(f"{bcolors.OKBLUE}您进入元宇宙了{bcolors.ENDC}")
66+
elif value == ':quit' or value == ':stop':
67+
if thread:
68+
client.close()
69+
close = True
70+
print(f"{bcolors.OKBLUE}正在退出中…{bcolors.ENDC}")
71+
thread.join()
72+
print(f"{bcolors.OKBLUE}元宇宙已退出{bcolors.ENDC}")
73+
thread = None
74+
if value == ':quit':
75+
print(f"{bcolors.OKBLUE}退出程序{bcolors.ENDC}")
76+
break
77+
pass
78+
elif value == 'help':
79+
help()
80+
else:
81+
if client:
82+
# 聊天模式
83+
client.send(value.encode('utf-8'))
84+
else:
85+
print(f'{bcolors.WARNING}还没接入元宇宙,请先输入 :start 接入{bcolors.ENDC}')
86+
client.close()

taiyangxue/meta/metaServer.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
from threading import Thread
2+
import socket
3+
from serversocket import ServerSocket
4+
import re
5+
6+
clients = {}
7+
def checkname(name, cid):
8+
for key, value in clients.items():
9+
if key != cid and value['name'] == name:
10+
return False
11+
return True
12+
13+
def sendMsg(msg, _from, _to=None):
14+
cid = _from['cid']
15+
closeCids = []
16+
for key, value in clients.items():
17+
if value['cid'] != cid and (not _to or value['name'] in _to):
18+
try:
19+
value['sock'].send(msg)
20+
except Exception as e:
21+
print(e)
22+
closeCids.append(key)
23+
24+
for _cid in closeCids:
25+
del clients[cid]
26+
27+
def onReceiveMsg(server, sock, ip, data):
28+
cid = f'{ip[0]}_{ip[1]}'
29+
data = data.decode('utf-8')
30+
print(f"收到数据: {data}")
31+
_from = clients[cid]
32+
if data.startswith('name:'):
33+
name = data[5:].strip()
34+
if not name:
35+
sock.send(f"不能设置空名称,否则其他人找不见你".encode('utf-8'))
36+
elif not checkname(name, cid):
37+
sock.send(f"这个名字{name}已经被使用,请换一个试试".encode('utf-8'))
38+
else:
39+
if not _from['name']:
40+
sock.send(f"{name} 很高兴见到你,现在可以畅游元宇宙了".encode('utf-8'))
41+
msg = f"新成员{name} 加入了元宇宙,和TA聊聊吧".encode('utf-8')
42+
sendMsg(msg, _from)
43+
else:
44+
sock.send(f"更换名称完成".encode('utf-8'))
45+
msg = f"{_from['name']} 更换名称为 {name},和TA聊聊吧".encode('utf-8')
46+
sendMsg(msg, _from)
47+
_from['name'] = name
48+
49+
elif '@' in data:
50+
targets = re.findall(r'@(.+?) ', data)
51+
print(targets)
52+
msg = f"{_from['name']}: {data}".encode('utf-8')
53+
sendMsg(msg, _from, targets)
54+
else:
55+
msg = f"{_from['name']}{data}".encode('utf-8')
56+
sendMsg(msg, _from)
57+
58+
def onCreateConn(server, sock, ip):
59+
cid = f'{ip[0]}_{ip[1]}'
60+
clients[cid] = {'cid': cid, 'sock': sock, '@allcount': 10, 'name': None}
61+
sock.send("你已经接入元宇宙,告诉我你的代号,输入格式为 name:lily.".encode('utf-8'))
62+
63+
def onCloseConn(server, sock, ip):
64+
cid = f'{ip[0]}_{ip[1]}'
65+
name = clients[cid]['name']
66+
if name:
67+
msg = f"{name} 从元宇宙中消失了".encode('utf-8')
68+
sendMsg(msg, clients[cid])
69+
del clients[cid]
70+
pass
71+
72+
if __name__ == '__main__':
73+
hostname = socket.gethostname()
74+
ip = socket.gethostbyname(hostname)
75+
server = ServerSocket(ip, 6000, onReceiveMsg, onCreateConn, onCloseConn)
76+
thread = None
77+
78+
while True:
79+
print("start 启动服务器")
80+
print("stop 关闭动服务器")
81+
print('quit 退出程序')
82+
value = input("输入指令:")
83+
value = value.strip()
84+
if value == 'start':
85+
if thread:
86+
print("服务器正在运行")
87+
else:
88+
thread = Thread(target=server.run)
89+
thread.start()
90+
print("服务器启动完成")
91+
pass
92+
elif value == 'stop' or value == 'quit':
93+
if thread:
94+
server.stop()
95+
print("服务器正在关闭中")
96+
thread.join()
97+
print("服务器已经关闭")
98+
thread = None
99+
if value == 'quit':
100+
print("退出程序")
101+
break
102+
pass
103+
elif value == 'show':
104+
print(clients)
105+
else:
106+
print("无效指令,请重新输入!")

taiyangxue/meta/serversocket.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import errno
2+
import queue
3+
import select
4+
import socket
5+
import sys
6+
7+
class ServerSocket:
8+
9+
def __init__(self, mode, port, onReceiveMsg, onCreateConn, onCloseConn, max_connections=1000, recv_bytes=2048):
10+
# Handle the socket's mode.
11+
# The socket's mode determines the IP address it binds to.
12+
# mode can be one of two special values:
13+
# localhost -> (127.0.0.1)
14+
# public -> (0.0.0.0)
15+
# otherwise, mode is interpreted as an IP address.
16+
if mode == "localhost":
17+
self.ip = mode
18+
elif mode == "public":
19+
self.ip = socket.gethostname()
20+
else:
21+
self.ip = mode
22+
23+
self.controlSocket = None
24+
self.clientSocket = []
25+
26+
# Handle the socket's port.
27+
# This should be a high (four-digit) for development.
28+
self.port = port
29+
if type(self.port) != int:
30+
print("port must be an int", file=sys.stderr)
31+
raise ValueError
32+
33+
# Save the callback
34+
self.onReceiveMsg = onReceiveMsg
35+
self.onCreateConn = onCreateConn
36+
self.onCloseConn = onCloseConn
37+
38+
# Save the number of maximum connections.
39+
self._max_connections = max_connections
40+
if type(self._max_connections) != int:
41+
print("max_connections must be an int", file=sys.stderr)
42+
raise ValueError
43+
# Save the number of bytes to be received each time we read from
44+
# a socket
45+
self.recv_bytes = recv_bytes
46+
47+
def run(self):
48+
# Start listening
49+
# Actually create an INET, STREAMing socket.socket.
50+
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
51+
# Make it non-blocking.
52+
self._socket.setblocking(0)
53+
# Bind the socket, so it can listen.
54+
self._socket.bind((self.ip, self.port))
55+
56+
self._socket.listen(self._max_connections)
57+
# Create a list of readers (sockets that will be read from) and a list
58+
readers = [self._socket]
59+
# Create a similar dictionary that stores IP addresses.
60+
# This dictionary maps sockets to IP addresses
61+
IPs = dict()
62+
self._stop = False
63+
64+
# Now, the main loop.
65+
print("TCP 服务器已启动")
66+
while readers and not self._stop:
67+
#print("Block until a socket is ready for processing.")
68+
read, _, err = select.select(readers, [], readers)
69+
# Deal with sockets that need to be read from.
70+
for sock in read:
71+
if sock is self._socket:
72+
# We have a viable connection!
73+
try:
74+
client_socket, client_ip = self._socket.accept()
75+
except Exception:
76+
break
77+
78+
# Make it a non-blocking connection.
79+
client_socket.setblocking(0)
80+
# Add it to our readers.
81+
readers.append(client_socket)
82+
# Make a queue for it.
83+
# queues[client_socket] = queue.Queue()
84+
IPs[client_socket] = client_ip
85+
self.onCreateConn(self, client_socket, client_ip)
86+
print(f"readers length {len(readers)}")
87+
else:
88+
# Someone sent us something! Let's receive it.
89+
try:
90+
data = sock.recv(self.recv_bytes)
91+
except socket.error as e:
92+
if e.errno == errno.ECONNRESET:
93+
# Consider 'Connection reset by peer'
94+
# the same as reading zero bytes
95+
data = None
96+
else:
97+
raise e
98+
if data:
99+
self.onReceiveMsg(self, sock, IPs[sock], data)
100+
else:
101+
#print("We received zero bytes, so we should close the stream")
102+
# Stop writing to it.
103+
# Stop reading from it.
104+
readers.remove(sock)
105+
sock.close()
106+
self.onCloseConn(self, sock, IPs[sock])
107+
108+
# Deal with erroring sockets.
109+
for sock in err:
110+
#print("Remove the socket from every list.")
111+
readers.remove(sock)
112+
# Close the connection.
113+
sock.close()
114+
115+
def stop(self):
116+
self._stop = True
117+
self._socket.close()

0 commit comments

Comments
 (0)