带有真实IP地址的python套接字服务器 [英] python Socket server with real ip address

查看:64
本文介绍了带有真实IP地址的python套接字服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am playing with my python server, but I'm through with using localhost and I want to go over the internet. My code thus-far is:

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()

运行此命令时出现错误:

When I run this i get the error:

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时,它说它处于活动状态.所以我认为我的某个地方连接有误.

I know the port works because when I use canyouseeme.org on port 9001 when my program is running it says its active and working. So I think I just have my connection wrong somewhere.

推荐答案

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

ip = '12.34.56.789' #Not my real ip address, its the one i got from whatismyip.org

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

The first problem is that '12.34.56.789' isn't a valid IP address at all. Each component has to fit in 8 bits (0-255); 789 is impossible. But I assume that isn't the actual code you're running, because the output shows 12.45.29.122.

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

The second problem is that you're using an address that isn't your real address.

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

Your machine presumably has an internal IP address, that can only be accessed from your LAN. Then, your router has an external IP address. The router uses a technique called Network Address Translation to let each machine on your LAN pretend that external address belongs to them, when they're acting as clients (which is why whatismyip.org shows you that address). But that doesn't work when they're acting as servers.

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

If you think about it, there's really no way it could work. If you make an outbound connection, and someone replies, the router knows that the reply should go to your machine. But if someone just comes along and talks to the router out of the blue, how could it know which machine to send the connection to?

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

If you're trying to connect from inside the same LAN, there's a very easy solution: use the server's real internal address, not the router's external address.

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

If you need to connect from outside, you can't, without some extra work. There are four ways around this:

  1. 为您的计算机提供一个真正的可公开寻址的IP地址(例如,将其放置在路由器的DMZ上).对于家庭用户来说,这通常甚至是不可行的选择,对于不知道自己在做什么的人来说,这是一个糟糕的选择(除非您希望在午餐时间让您的机器成为某人的僵尸网络的一部分).

  1. Give your machine a real publicly-addressable IP address (e.g., by putting it on the router's DMZ). This is generally not even an option for home users, and it's a bad option for people who don't know what they're doing (unless you want your machine to be part of someone's botnet by lunchtime).

在路由器的配置中设置静态端口转发.对于每个路由器而言,这是不同的,但是您的想法是告诉它如果有人来寻找端口9001,请始终将其发送到机器192.168.1.64".

Set up static port forwarding in your router's configuration. This is different for each router, but the idea is that you tell it "if someone comes looking for port 9001, always send them to machine 192.168.1.64".

使用UPnP动态设置端口转发.

Use UPnP to set up port forwarding dynamically.

设置NAT打孔.

选项3和4比较复杂,我认为选项2是您想要的选项,所以我不再赘述.

Options 3 and 4 are more complex, and I think option 2 is the one you want, so I won't explain them.

最重要的是:

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.

You've told the server explicitly "listen on 192.168.1.64". Even if you put your server machine on the DMZ, so it had addresses 192.168.1.64 and 12.45.29.122, your program is only listening for connections on the first one, so nobody would be able to reach it using the second. If you want to listen on all addresses, use 0.0.0.0.

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

In the edited version, you're now listening on 0.0.0.0, and connecting to the router's public IP, and you claim to have set up port forwarding on the router, and you're still getting the exact same error.

如果这都是正确的,那么可能会出现三个明显的错误:

If that's all correct, there are three obvious things that could be going wrong:

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

您可以执行一些测试来缩小范围.

There are a few tests you can do to narrow things down.

  1. 打开两个端子.在其中之一中,键入nc -kl 9001.在另一个中,键入nc 12.34.56.78 9001.它们应该连接起来,所以您在一个窗口中键入的任何内容都会显示在另一个窗口中(可能仅在您按下Return键之后).如果可行,则端口转发正常,并且没有防火墙问题,因此这是您的代码中的问题.

  1. Open two terminals. In one, type nc -kl 9001. In the other, type nc 12.34.56.78 9001. They should connect up, so anything you type into one window appears in the other (maybe only after you hit Return). If that works, the port forwarding is working, and there's no firewall problem, so it's a problem in your code.

如果这不起作用,请准确张贴您在每个窗口中看到的内容.然后,按住Ctrl-C键选择第二个nc,然后键入nc 192.168.1.64 9001.如果这现在可行,则除非您设置的聪明的防火墙允许相同主机(或相同接口)连接但不允许远程连接,否则端口转发设置都不正确.

If that didn't work, please post exactly what you saw in each window. Then Ctrl-C the second nc, and type nc 192.168.1.64 9001. If that now works, either the port forwarding isn't set up right, unless you have a clever firewall that allows same-host (or same-interface) connections but not remote connections.

如果两个都不起作用,则可能是防火墙问题. (除非您对IP地址或其他内容有误.)您可能可以在某处找到日志,但是如果不知道所使用的平台和所使用的防火墙,很难提供很多帮助. (此外,这可能是与SO不同的站点的问题.)

If neither one worked, it's probably a firewall problem. (Unless you're wrong about your IP addresses or something.) You can probably find logs somewhere, but without knowing what platform you're on and what firewall you're using it's hard to offer much help. (Also, that's probably a problem for a different site than SO.)

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

If you're on Windows, or some linux distros, you need to get a copy of nc (netcat) from somewhere; on most linux distros, and Mac, it should be built in. Also, GNU, BSD, and Hobbit nc are slightly different, so if nc -kl 6000 gives you an error, you might have to read the man page or --help. (If I remember right, Hobbit nc requires -l -p6000, BSD requires -l 6000, GNU allows either.)

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

Or you may want ncat, a re-implementation of netcat that I know can handle the syntax I used above, and has a single-file static executable for Windows.

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

If you can't get started with nc, at least try changing your code to connect to 192.168.1.64 instead of 12.34.56.78. If that fixes the problem, at least you'll know it's either port forwarding or a firewall that allows same-host/interface connections but not remote.

这篇关于带有真实IP地址的python套接字服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆