在公网设置一个中间服务器111.222.111.2222
from socket import *
import threading
server_addr = ('111.222.111.2222',6000)
udpSerSock = socket(AF_INET,SOCK_DGRAM)
udpSerSock.bind(server_addr)
hostDict={} #保存登入的客户端
def revMsg():
print("start rev:")
while True:
data, address = udpSerSock.recvfrom(1024)
try:
(msg_type,msg_hostname,msg_contain)=str(data).split('|')
except:
print('[error msg!]', str(data))
continue
# 根据消息的类型作出回应
if int(msg_type)==9:#保存连接
udpSerSock.sendto('%d|%s|%s' % (9,"Server","keep live"), address)
elif int(msg_type)==0:#注册客户端ip和端口
hostDict[msg_hostname]="%s:%s" % (address[0],address[1])
print('[login: %s:%s]:%s' % (address[0],address[1],msg_hostname))
udpSerSock.sendto('%d|%s|%s' % (0,address[0],address[1]), address)
elif int(msg_type)==1:#返回在线的客户端信息
print('[query: %s]' % (msg_hostname))
udpSerSock.sendto('%d|%s|%s' % (1,str(hostDict)," "), address)
elif int(msg_type)==2:#p2p连接指定客户端
online_list=hostDict.keys()
if msg_hostname in online_list:
item=hostDict[msg_hostname]
(B_ip,B_port)=item.split(':')
print('[%s connect to :%s]' % (address[0],B_ip))
udpSerSock.sendto('%d|%s|%s' % (2,B_ip,B_port), address)
# 通知指定客户端响应p2p连接
print('[Remind B]')
udpSerSock.sendto('%d|%s|%s' % (4,address[0],address[1]), (B_ip,int(B_port)))
else:#指定客户端不存在
print('[B offline]')
udpSerSock.sendto('%d|%s|%s' % (3,"0","0"), address)
#开始监听消息
try:
thread = threading.Thread(target = revMsg)
thread.setDaemon(True)
thread.start()
except:
print "Error: unable to start thread"
#接受输入
while True:
msg = raw_input(">>")
if str(msg).strip()=='exit':
print("exit!")
break
# udpSerSock.sendto(msg, address)
udpSerSock.close()
客户端代码:
import socket
import threading
import time
server_addr = ('111.222.111.2222', 6000)
udpSerSock= socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Clinet_Name="clinet_A"
def heartbeat():
while True:
udpSerSock.sendto('%d|%s|%s' % (9,"keep ","live"), server_addr)
time.sleep(10)
def revMsg():
global peer_ip,peer_port
print(" start rev:")
while True:
data, addr = udpSerSock.recvfrom(1024)
try:
(msg_type,msg_arg1,msg_arg2)=str(data).split('|')
except:
print('[error msg!]', str(data))
continue
if int(msg_type)==9:
continue
elif int(msg_type)==0:
print('[login success: %s]' % (str(data)))
elif int(msg_type)==1:
print("online hosts:\n%s"% (msg_arg1))
elif int(msg_type)==2:
print('[peer online]')
peer_ip=msg_arg1
peer_port=msg_arg2
elif int(msg_type)==3:
print('[peer offline]')
elif int(msg_type)==4:
print('[respond peer]')
udpSerSock.sendto('%d|%s|%s' % (9,"hello"," "), (msg_arg1,int(msg_arg2)))
elif int(msg_type)==5:
print('[peer msg]:%s'% msg_arg1)
else:
print('[error Type!]', str(data))
try:
rev_thread = threading.Thread(target = revMsg)
rev_thread.setDaemon(True)
rev_thread.start()
heat_thread=threading.Thread(target = heartbeat)
heat_thread.setDaemon(True)
heat_thread.start()
except:
print "Error: unable to start thread"
# ========================
host_name="Noname"
# 依次执行0,1,2,3命令后完成p2p连接并可以直接聊天
while True:
comd = raw_input("Commend[0,1,2,3]>>")
# query online host
if str(comd).strip()=='0':
host_name = raw_input("hostname>>")
udpSerSock.sendto('%d|%s|%s' % (0,str(host_name).strip()," "), server_addr)
elif str(comd).strip()=='1':
print("get online host...")
udpSerSock.sendto('%d|%s|%s' % (1," "," "), server_addr)
elif str(comd).strip()=='2':
peer_name = raw_input("peer_name>>")
print("get peer ip...")
udpSerSock.sendto('%d|%s|%s' % (2,str(peer_name).strip()," "), server_addr)
elif str(comd).strip()=='3':
msg = raw_input("Msg>>")
udpSerSock.sendto('%d|%s|%s' % (5,str(msg).strip()," "), (peer_ip,int(peer_port)))
if str(comd).strip()=='exit':
print("exit!")
break
udpSerSock.close()