我正在玩我的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时,它说它活跃且工作正常。所以我想我的连接错了。
答案 0 :(得分:15)
ip =&#39; 12.34.56.789&#39; #Not我的真实IP地址,它是我从whatismyip.org获得的地址
第一个问题是&#39; 12.34.56.789&#39;根本不是有效的IP地址。每个组件必须适合8位(0-255); 789是不可能的。但我认为这不是您正在运行的实际代码,因为输出显示为12.45.29.122。
第二个问题是,您使用的地址不是您的真实地址。
您的机器可能有一个内部IP地址,只能从您的LAN访问。然后,您的路由器具有外部IP地址。路由器使用一种称为网络地址转换的技术让局域网中的每台机器假装外部地址属于它们,当它们作为客户端时(这就是为什么whatismyip.org会向您显示该地址)。但是,当他们充当服务器时,这并不起作用。
如果你考虑一下,那真的没办法。如果您进行出站连接,并且有人回复,则路由器知道回复应该发送到您的计算机。但是,如果有人刚刚出现并且明确地与路由器交谈,那么它怎么知道将连接发送到哪台机器呢?
如果您尝试从同一局域网内部进行连接,那么这是一个非常简单的解决方案:使用服务器的真实内部地址,而不是路由器的外部地址。
如果您需要从外部进行连接,则无法进行额外的工作。有四种方法:
为您的机器提供真正可公开寻址的IP地址(例如,将其放在路由器的DMZ上)。这通常不是家庭用户的选择,对于不了解他们正在做什么的人来说这是一个不好的选择(除非你希望你的机器成为某人的一部分)僵尸网络午餐时间)。
在路由器的配置中设置静态端口转发。对于每个路由器来说这是不同的,但是想法是你告诉它&#34;如果有人来寻找端口9001,总是将它们发送到机器192.168.1.64&#34;。
使用UPnP动态设置端口转发。
设置NAT打孔。
选项3和4更复杂,我认为选项2是你想要的,所以我不会解释它们。
最重要的是:
HOST, PORT = "192.168.1.64", 9001
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
您已明确告知服务器&#34;请听192.168.1.64&#34;。即使您将服务器机器放在DMZ上,因此它的地址为192.168.1.64和12.45.29.122,您的程序只会侦听第一个上的连接,因此没有人能够使用第二个连接。如果要监听所有地址,请使用0.0.0.0。
在编辑后的版本中,您现在正在收听0.0.0.0,并连接到路由器的公共IP,并且您声称已在路由器上设置端口转发,并且您已经在路由器上设置了端口转发功能。仍然得到完全相同的错误。
如果这一切都正确的话,有三个明显的问题可能会出错:
您可以采取一些措施来缩小范围。
打开两个终端。在其中一个中,键入nc -kl 9001
。在另一个中,键入nc 12.34.56.78 9001
。它们应该连接起来,所以你在一个窗口中键入的内容会出现在另一个窗口中(可能只有在你点击Return后)。如果可行,则端口转发正常,并且没有防火墙问题,因此在您的代码中存在问题。
如果这不起作用,请准确发布您在每个窗口中看到的内容。然后按Ctrl-C第二个nc
,然后输入nc 192.168.1.64 9001
。如果现在可以正常工作,则端口转发不能正确设置,除非您有一个聪明的防火墙允许相同主机(或同一接口)连接但不允许远程连接。
如果两者都不起作用,则可能是防火墙问题。 (除非您对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。如果这样可以解决问题,至少您知道它是端口转发还是允许相同主机/接口连接而不是远程连接的防火墙。