如何在服务器上实现tcp端口转发

一.关于中间人模式

        在两台内网设备的通讯中,有时需要一台公网设备(提供公网IP)参与转发,此时,这台公网设备(服务器)充当“中间人”。

参考:(7条消息) 设计模式:中间人模式_leonhover的博客-CSDN博客

二.我们的案例

          在我们的案例中,两台内网设备我们称作client(客户端)和slave(从机),(我之所以以clientslave命名,是因为在我的项目中,client是一台遥控装置,而slave是被操控的设备)。在client和slave通信的过程中,需要一台公网服务器帮忙转发,同时要求client和slave在连接服务器是有密码验证。鉴此,我写了如下python脚本

#-*- coding:utf-8 -*-
import socket
import threading

PASSWORDA = "1234" #用不同的密码确定slave和client两个客户端的身份 
PASSWORDB = "5678"

# global server_socket
# global slave_socket

class ClientThread(threading.Thread):
    def __init__(self, con, addr):
        super().__init__()
        self.con = con
        self.addr = addr
        self.index = -1

    def run(self):
        try:
            # 请求客户端输入密码
            self.con.send("开始验证 ".encode('UTF-8'))
            # 接收客户端输入的密码
            input_password = self.con.recv(1024).strip().decode('UTF-8')
            # 验证密码是否正确
            if input_password == PASSWORDA:
                if "client" in list(socket_list.keys()):
                    del socket_list["client"]
                socket_list.update({"client":self.con})
                global client_socket
                client_socket = self.con
                self.index = list(socket_list.keys()).index("client")
                self.con.send("验证成功!".encode('UTF-8'))
                print(f"验证成功,连接来自 {self.addr} !")
            elif input_password == PASSWORDB:
                if "slave" in list(socket_list.keys()):
                    del socket_list["slave"]
                socket_list.update({"slave":self.con})
                global slave_socket
                slave_socket = self.con
                self.index = list(socket_list.keys()).index("slave")
                self.con.send("验证成功!".encode('UTF-8'))
                print(f"验证成功,连接来自 {self.addr} !")
            else:
                print(f"验证失败,拒绝 {self.addr} !")
                self.con.close()
            while True:
                # 接收客户端发送的消息
                if len(socket_list) == 1:
                    self.con.send(("等待另一端连接").encode('UTF-8'))
                    while len(socket_list) == 1:
                        None
                data = self.con.recv(1024)
                if not data:
                    break
                message = data.decode('UTF-8')
                print(f"接收 {self.addr}: {message}")
                
                socket_list[list(socket_list.keys())[1-self.index]].send(data)
                
            print(f"丢失连接 {self.addr} !")
        except Exception as e:
            print(f"连接错误 {self.addr}: {e} !")
        finally:
            self.con.close()
            try:
               del socket_list[list(socket_list.keys())[self.index]]
            except:
                None
            self.index=-1


host = ""
port = 1000
socket_list = {}

if __name__ == '__main__':
    host_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host_socket.bind((host, port))
    host_socket.listen(2)

    while True:
        con, addr = host_socket.accept()
        client_thread = ClientThread(con, addr)
        client_thread.start()

三.注意

            在使用端口1000时,需要确保服务器防火墙打开1000端口,(如果是云服务器,配置好安全规则),以Ubuntu为例,打开1000端口:

sudo ufw allow 1000

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值