python套接字服务器与真正的IP地址

问题描述 投票:4回答:1

我正在玩我的python服务器,但我使用localhost,我想通过互联网。我的代码到目前为止是:

import socket
import threading
import socketserver

class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):

    def handle(self):
        data = self.request.recv(1024)
        cur_thread = threading.current_thread()
        response = "{}: {}".format(cur_thread.name, data)
        self.request.sendall(b'worked') 

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

def client(ip, port, message):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((ip, port))
    try:
        sock.sendall(message)
        response = sock.recv(1024)
        print("Received: {}".format(response))
    finally:
        sock.close()

if __name__ == "__main__":
    # Port 0 means to select an arbitrary unused port
    HOST, PORT = "0.0.0.0", 9001

    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
    ip, port = server.server_address

    # Start a thread with the server -- that thread will then start one
    # more thread for each request
    server_thread = threading.Thread(target=server.serve_forever)
    # Exit the server thread when the main thread terminates
    server_thread.daemon = True
    server_thread.start()
    print("Server loop running in thread:", server_thread.name)
    ip = '12.34.56.789' #Not my real ip address This is just to hide my ip
    print(ip, PORT)

    client(ip, PORT, b'Hello World 1')
    #client(ip, port, b'Hello World 2')
    #client(ip, port, b'Hello World 3')

    server.shutdown()

当我运行这个我得到错误:

Server loop running in thread: Thread-1
12.34.56.789 9001
Traceback (most recent call last):
  File "C:/Python32/serverTesty.py", line 43, in <module>
    client(ip, PORT, b'Hello World 1')
  File "C:/Python32/serverTesty.py", line 18, in client
    sock.connect((ip, port))
socket.error: [Errno 10061] No connection could be made because the target machine actively refused it

我知道端口是可行的,因为当我的程序运行时,当我在端口9001上使用canyouseeme.org时,它表示它的活动和工作。所以我想我的连接错了。

python sockets ip
1个回答
15
投票

ip = '12 .34.56.789'#Not我的真实IP地址,它是我从whatismyip.org获得的地址

第一个问题是'12 .34.56.789'根本不是有效的IP地址。每个组件必须适合8位(0-255); 789是不可能的。但我认为这不是你正在运行的实际代码,因为输出显示12.45.29.122。

第二个问题是您使用的地址不是您的真实地址。

您的机器可能有一个内部IP地址,只能从您的LAN访问。然后,您的路由器具有外部IP地址。路由器使用一种称为网络地址转换的技术让局域网中的每台机器假装外部地址属于它们,当它们充当客户端时(这就是为什么whatismyip.org会向您显示该地址)。但是,当它们充当服务器时,这不起作用。

如果你仔细想想,它真的没办法。如果您进行出站连接,并且有人回复,则路由器知道回复应该发送到您的计算机。但是,如果有人刚刚出现并且与路由器进行了突然交谈,那么它怎么知道将连接发送到哪台机器呢?

如果您尝试从同一LAN内部进行连接,则可以使用服务器的真实内部地址,而不是路由器的外部地址。

如果你需要从外面连接,你不能没有一些额外的工作。有四种方法:

  1. 为您的机器提供真正可公开寻址的IP地址(例如,将其放在路由器的DMZ上)。这通常不是家庭用户的选择,对于不知道自己在做什么的人来说这是一个不好的选择(除非你希望你的机器在午餐时间成为某人僵尸网络的一部分)。
  2. 在路由器的配置中设置静态端口转发。这对于每个路由器来说都是不同的,但想法是你告诉它“如果有人来寻找端口9001,总是将它们发送到机器192.168.1.64”。
  3. 使用UPnP动态设置端口转发。
  4. 设置NAT打孔。

选项3和4更复杂,我认为选项2是你想要的,所以我不会解释它们。

最重要的是:

HOST, PORT = "192.168.1.64", 9001

server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)

你已经明确告诉服务器“监听192.168.1.64”。即使您将服务器机器放在DMZ上,因此它的地址为192.168.1.64和12.45.29.122,您的程序只会侦听第一个上的连接,因此没有人能够使用第二个连接。如果要监听所有地址,请使用0.0.0.0。

在编辑版本中,您现在正在侦听0.0.0.0,并连接到路由器的公共IP,并且您声称已在路由器上设置端口转发,并且您仍然得到完全相同的错误。

如果这一切都是正确的,那么有三个显而易见的事情可能会出错:

  1. 你实际上并不是端口转发;设置有问题。
  2. 你实际上并没有在0.0.0.0:9001上听。
  3. 您有防火墙阻止连接。

您可以采取一些测试来缩小范围。

  1. 打开两个终端。在其中一个,键入nc -kl 9001。在另一方面,键入nc 12.34.56.78 9001。它们应该连接起来,所以你在一个窗口中键入的内容会出现在另一个窗口中(可能只有在你点击Return后)。如果可行,端口转发正常,并且没有防火墙问题,因此在您的代码中存在问题。
  2. 如果这不起作用,请准确发布您在每个窗口中看到的内容。然后Ctrl-C第二个nc,并输入nc 192.168.1.64 9001。如果现在有效,则端口转发设置不正确,除非您有一个聪明的防火墙允许相同主机(或同一接口)连接但不允许远程连接。
  3. 如果两个都没有工作,那可能是防火墙问题。 (除非你对你的IP地址或其他东西错了。)你可能会在某个地方找到日志,但不知道你在哪个平台以及你正在使用什么防火墙很难提供很多帮助。 (另外,对于不同于SO的网站而言,这可能是一个问题。)

如果您使用的是Windows或某些Linux发行版,则需要从某处获取nc(netcat)的副本;在大多数Linux发行版和Mac上,它应该内置。而且,GNU,BSD和Hobbit nc略有不同,所以如果nc -kl 6000给你一个错误,你可能必须阅读手册页或--help。 (如果我没记错的话,Hobbit nc需要-l -p6000,BSD需要-l 6000,GNU允许。)

或者您可能需要ncat,我知道可以处理上面使用的语法的netcat的重新实现,并且具有Windows的单文件静态可执行文件。

如果你无法开始使用nc,至少尝试更改代码以连接到192.168.1.64而不是12.34.56.78。如果这解决了问题,至少你会知道它是端口转发或允许相同主机/接口连接而不是远程连接的防火墙。

© www.soinside.com 2019 - 2024. All rights reserved.