我正在使用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内部进行连接,则有一个非常简单的解决方案:使用服务器的真实内部地址,而不是路由器的外部地址。
如果需要从外部进行连接,则无需做一些额外的工作就可以了。有四种解决方法:
选项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,并且您声称已在路由器上设置了端口转发,并且仍然遇到完全相同的错误。
如果这一切都是正确的,那么可能会出现三个明显的错误:
您可以进行一些测试来缩小范围。
nc -kl 9001
。在另一个中,键入nc 12.34.56.78 9001
。它们应该连接起来,所以您在一个窗口中键入的任何内容都会显示在另一个窗口中(可能仅在您按下Return键之后)。如果可行,则端口转发正常,并且没有防火墙问题,因此这是您的代码中的问题。 nc
,然后键入nc 192.168.1.64 9001
。如果这现在可行,则除非正确设置了端口转发功能,否则除非您拥有一个聪明的防火墙,该防火墙允许同一主机(或同一接口(interface))连接,但不允许远程连接。 如果您使用的是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/