152 lines
4.5 KiB
Python
152 lines
4.5 KiB
Python
import socket
|
|
import threading
|
|
import uuid
|
|
|
|
from utils import *
|
|
|
|
co_server_port = 5000
|
|
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
tcp_sock.bind(('0.0.0.0', co_server_port))
|
|
tcp_sock.listen(5)
|
|
|
|
servers = {}
|
|
|
|
clients = {}
|
|
|
|
co_server_token = f"co_server_{uuid.uuid4().hex[:8]}"
|
|
my_charactor = 'co_server'
|
|
|
|
|
|
def handle_punch_request(client_name, server_name):
|
|
client = clients[client_name]
|
|
server = servers[server_name]
|
|
udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
udp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
udp_sock.bind(('0.0.0.0', 5002))
|
|
udp_sock.settimeout(20)
|
|
co_server_punch_port = udp_sock.getsockname()[1]
|
|
print(f'向客户端和服务端发起端口暴露请求到{co_server_punch_port}')
|
|
send_action_tcp(server['sock'], 'punch_request', {
|
|
'co_server_punch_port': co_server_punch_port
|
|
})
|
|
send_action_tcp(client['sock'], 'punch_request', {
|
|
'co_server_punch_port': co_server_punch_port
|
|
})
|
|
client_punch_port = 0
|
|
server_punch_port = 0
|
|
count = 0
|
|
while client_punch_port == 0 or server_punch_port == 0:
|
|
action, message, data, addr = recv_udp(udp_sock)
|
|
if action == 'server_punch_port':
|
|
print(f'获取到服务端打洞端口{addr[1]}')
|
|
server_punch_port = addr[1]
|
|
if action == 'client_punch_port':
|
|
print(f'获取到客户端打洞端口{addr[1]}')
|
|
client_punch_port = addr[1]
|
|
time.sleep(0.1)
|
|
count += 1
|
|
udp_sock.close()
|
|
print('发送打洞请求')
|
|
send_action_tcp(client['sock'], 'punch_to', {
|
|
'server_name': server_name,
|
|
'server_token': server['token'],
|
|
'target_addr': (server['addr'][0], server_punch_port)
|
|
})
|
|
send_action_tcp(server['sock'], 'punch_to', {
|
|
'client_name': client_name,
|
|
'client_token': client['token'],
|
|
'target_addr': (client['addr'][0], client_punch_port)
|
|
})
|
|
|
|
|
|
def handle_server(sock, addr, server_info):
|
|
server_name = server_info['name']
|
|
server_token = server_info['token']
|
|
if server_name in servers:
|
|
send_action_tcp(sock, 'bye', 'server already exists')
|
|
return
|
|
send_action_tcp(sock, 'co_server_hello', {
|
|
'charactor': my_charactor,
|
|
'token': co_server_token,
|
|
})
|
|
servers[server_name] = {
|
|
'sock': sock,
|
|
'addr': addr,
|
|
'name': server_name,
|
|
'token': server_token,
|
|
}
|
|
while True:
|
|
try:
|
|
action, message, data = recv_tcp(sock)
|
|
if action == 'ping':
|
|
send_action_tcp(sock, 'pong')
|
|
else:
|
|
send_action_tcp(sock, 'bye', 'unknown action')
|
|
break
|
|
except Exception as e:
|
|
print(e)
|
|
send_action_tcp(sock, 'bye', f'error: {e}')
|
|
break
|
|
sock.close()
|
|
del servers[server_name]
|
|
|
|
|
|
def handle_client(sock, addr, client_info):
|
|
client_name = client_info['name']
|
|
client_token = client_info['token']
|
|
clients[client_name] = {
|
|
'sock': sock,
|
|
'addr': addr,
|
|
'token': client_token,
|
|
}
|
|
while True:
|
|
try:
|
|
action, message, data = recv_tcp(sock)
|
|
if action == 'ping':
|
|
send_action_tcp(sock, 'pong')
|
|
elif action == 'punch_request':
|
|
server_name = message['server_name']
|
|
if server_name in servers:
|
|
handle_punch_request(client_name, server_name)
|
|
else:
|
|
send_action_tcp(sock, 'error', f"服务器不存在: {server_name}")
|
|
break
|
|
except Exception as e:
|
|
print(e)
|
|
send_action_tcp(sock, 'bye', f'error: {e}')
|
|
break
|
|
sock.close()
|
|
del clients[client_name]
|
|
|
|
|
|
def handle_connect(sock, addr):
|
|
try:
|
|
action, message, data = recv_tcp(sock)
|
|
except Exception as e:
|
|
print(e)
|
|
send_action_tcp(sock, 'error', f"无法解析数据")
|
|
return
|
|
if action == 'server_hello':
|
|
handle_server(sock, addr, message)
|
|
elif action == 'client_hello':
|
|
handle_client(sock, addr, message)
|
|
else:
|
|
print(f"未知连接:{addr} -> {action}")
|
|
sock.close()
|
|
|
|
|
|
def main():
|
|
print(f"{my_charactor} 启动")
|
|
while True:
|
|
conn, addr = tcp_sock.accept()
|
|
print(f"{my_charactor} 收到来自 {addr} 的连接")
|
|
threading.Thread(
|
|
target=handle_connect,
|
|
args=(conn, addr),
|
|
daemon=True
|
|
).start()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|