【发布时间】:2020-10-14 05:31:56
【问题描述】:
我正在尝试使用 Python 3 开发 TCP 代理库。我的代码基于由 LiveOverflow 编写的 Python 2 示例代码。他的原始代码在his video。我的代理库旨在像这样工作:有一个代理对象,其中包含一个服务器端对象和一个客户端对象。客户端对象模仿服务器,而服务器端对象模仿客户端。两者通过父代理对象相互传递数据。为了启动代理,使用该库的脚本使用客户端将托管的端口以及服务器端将连接到的 IP 地址和端口来实例化代理。代码如下:
TCP.py:
from threading import Thread
import socket as sock
class proxy():
def __init__(self, cSidePort, sSideIP, sSidePort, connections = 1, packetSize = 4096):
self.connections = connections
self.cSide = clientSide(self, cSidePort)
print('proxy: initialized cSide')
self.sSide = serverSide(self, sSideIP, sSidePort)
print('proxy: initialized sSide')
self.cSide.start()
print('proxy: started cSide')
self.sSide.start()
print('proxy: started cSide')
class clientSide(Thread):
def __init__(self, parentProxy, port):
Thread.__init__(self)
print('clientSide: Thread.__init__ called')
self.parentProxy = parentProxy
self.port = port
self.socket = sock.socket(sock.AF_INET, sock.SOCK_STREAM)
print('clientSide: socket created')
self.socket.bind(('', self.port))
print('clientSide: socket bound')
print('clientSide: Ip address of the proxy is: {}'.format(sock.gethostbyname(sock.gethostname())))
self.socket.listen(self.parentProxy.connections)
print('clientSide: socket listening')
self.conn, self.connAddr = self.socket.accept()
print('clientSide: socket has connection')
def run(self):
print('clientSide: run called')
while(True):
data = self.conn.recv(self.parentProxy.packetSize)
if data:
self.parentProxy.sSide.sendall(data)
def sendall(self, data):
print('clientSide: sendall called')
self.conn.sendall(data)
class serverSide(Thread):
def __init__(self, parentProxy, port, serverIP, serverPort):
Thread.__init__(self)
self.parentProxy = parentProxy
self.port = port
self.serverIP = serverIP
self.serverPort = serverPort
self.socket = sock.socket(sock.AF_INET, sock.SOCK_STREAM)
self.socket.bind(('', self.port))
self.socket.connect((self.serverIP, self.serverPort))
def run(self):
while(True):
data = self.socket.recv(4096)
if data:
self.parentProxy.sSide.sendall(data)
def sendall(self, data):
self.socket.sendall(data)
exampleProxy.py:
import TCP
import socket as sock
tcpProxy = TCP.proxy(443, sock.gethostbyname('example.com'), 443)
然后我从 Powershell 调用 exampleProxy.py:
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Try the new cross-platform PowerShell https://aka.ms/pscore6
Loading profile for aweso...
Profile loaded.
PS [*****] C:\Users\*****\Documents\Source\Python\proxy> python exampleProxy.py
clientSide: Thread.__init__ called
clientSide: socket created
clientSide: socket bound
clientSide: Ip address of the proxy is: 192.168.**.*
clientSide: socket listening
如调试所示,代理脚本在clientSide 类中的self.socket.accept() 处滞后。当我在 iPhone 上打开 Microsoft Edge 并键入代理打印的 IP 地址时,浏览器尝试连接到该页面时超时。然后我在 Windows WiFi 属性中检查代理的 IP 地址,这与代理报告的不同。我在手机的浏览器中输入该 IP,但没有任何反应。我还尝试通过我的 android 平板电脑连接到代理,结果相同。我知道运行代理的计算机可以托管,因为我已经在它和我的笔记本电脑之间进行了套接字通信。
现在的问题是:为什么代理实际上没有连接?
编辑以获取更多信息:
我创建了一个基本的网络托管脚本来表明计算机能够托管套接字连接:
main.py:
import socket
def web_page():
with open('index.html', 'rb') as indexFile:
html = indexFile.read()
return html
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)
while True:
conn, addr = s.accept()
print('Got a connection from {}\n\n'.format(addr))
request = conn.recv(1024)
print('Request: {}'.format(request))
response = web_page()
conn.send(b'HTTP/1.1 200 OK\n')
conn.send(b'Content-Type: text/html\n')
conn.send(b'Connection: close\n\n')
conn.sendall(response)
conn.close()
<!doctype html>
<html>
<head>
<title>Test Page</title>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
div {
width: 600px;
margin: 5em auto;
padding: 2em;
background-color: #fdfdff;
border-radius: 0.5em;
box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
}
a:link, a:visited {
color: #38488f;
text-decoration: none;
}
@media (max-width: 700px) {
div {
margin: 0 auto;
width: auto;
}
}
</style>
</head>
<body>
<div>
<h1>This is a test.</h1>
<p>If you are reading this, it works!</p>
</div>
</body>
</html>
我运行 main.py 并在手机浏览器中调用计算机的 IP 地址。这给了我预期的网页。然后我再次使用端口 443 尝试了 main.py。这导致了无连接问题。我将尝试在代理示例中更改端口。
【问题讨论】: