python实现UDP打洞

基于python 实现 UDP打洞

在公网设置一个中间服务器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()

你可能感兴趣的:(python,网络,python,socket,UDP打洞,p2p通信)