我正在使用python服务器,但是我已经使用localhost了,我想通过Internet访问。到目前为止,我的代码是:

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时,它表示该端口处于事件状态。因此,我认为我的某个地方连接有误。

最佳答案



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

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

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

如果您考虑一下,它实际上是不可能的。如果您建立出站连接,并且有人答复,则路由器知道答复应该发给您的计算机。但是,如果有人刚走过来并突然与路由器对话,它怎么知道将连接发送到哪台计算机?

如果您尝试从同一LAN内部进行连接,则有一个非常简单的解决方案:使用服务器的真实内部地址,而不是路由器的外部地址。

如果需要从外部进行连接,则无需做一些额外的工作就可以了。有四种解决方法:

  • 为您的计算机提供一个真正的可公开寻址的IP地址(例如,将其放置在路由器的DMZ上)。对于家庭用户来说,这通常甚至是不可行的选择,而对于不知道自己在做什么的人来说,这是一个糟糕的选择(除非您希望在午餐时间让您的机器成为某个人的僵尸网络的一部分)。
  • 在路由器的配置中设置静态端口转发。每个路由器都不同,但是您的想法是告诉它“如果有人来寻找端口9001,请始终将其发送到机器192.168.1.64”。
  • 使用UPnP动态设置端口转发。
  • 设置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,并连接到路由器的公共(public)IP,并且您声称已在路由器上设置了端口转发,并且仍然遇到完全相同的错误。

    如果这一切都是正确的,那么可能会出现三个明显的错误:
  • 您实际上不是端口转发;设置有问题。
  • 您实际上不是在听0.0.0.0:9001。
  • 您的防火墙阻止了连接。

  • 您可以进行一些测试来缩小范围。
  • 打开两个终端。在其中一个中,键入nc -kl 9001。在另一个中,键入nc 12.34.56.78 9001。它们应该连接起来,所以您在一个窗口中键入的任何内容都会显示在另一个窗口中(可能仅在您按下Return键之后)。如果可行,则端口转发正常,并且没有防火墙问题,因此这是您的代码中的问题。
  • 如果这不起作用,请准确张贴您在每个窗口中看到的内容。然后按Ctrl-C第二个nc,然后键入nc 192.168.1.64 9001。如果这现在可行,则除非正确设置了端口转发功能,否则除非您拥有一个聪明的防火墙,该防火墙允许同一主机(或同一接口(interface))连接,但不允许远程连接。
  • 如果两个都不起作用,则可能是防火墙问题。 (除非您对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。如果这样可以解决问题,那么至少您会知道这是端口转发或允许相同主机/接口(interface)连接但不允许远程连接的防火墙。

    关于带有真实IP地址的python套接字服务器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12631791/

    10-11 22:55
    查看更多