在 python 中使用套接字编写代理 Web 服务器
Write proxy web server using socket in python
这是我在大学计算机网络课程研讨会上的代码。
要求:写一个代理网络服务器。从浏览器端口 8888 接收 HTTP 请求,并向 Web 服务器端口 80 发送 HTTP 请求。我似乎无法向 Web 服务器发送请求。
你能告诉我在这种情况下我的错误吗?
非常感谢
import socket
import sys
import _thread
import traceback
import ssl
def CreateServer(host, port):
Server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Server.bind((host,port))
Server.listen(5)
return Server
def ReadRequest(Client):
re = ""
Client.settimeout(10.0)
try:
re = Client.recv(1024).decode()
while (re):
re = re + Client.recv(1024).decode()
except socket.timeout: # fail after 1 second of no activity
if not re:
print("Didn't receive data! [Timeout]")
finally:
return re
#2. Client connect Server + 3. Read HTTP Request
def ReadHTTPRequest(Server):
re = ""
while (re == ""):
Client, address = Server.accept()
print("Client: ", address," da ket noi toi Server")
re = ReadRequest(Client)
return Client,address, re
def proxy_server(webserver, port, conn, data, addr):
print("{} {} {} {}".format(webserver, port, conn, addr))
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(10.0)
s.connect((webserver, port))
s.sendall(data)
while 1:
reply = s.recv(1024)
if len(reply) > 0:
conn.send(reply)
print("[*] Request sent: {} > {}".format(addr[0],webserver))
else:
break
s.close()
conn.close()
except Exception as e:
print(e)
traceback.print_exc()
s.close()
conn.close()
sys.exit(1)
def conn_string(Client,Request,addr):
try:
#print(addr)
first_line=Request.split('\n')[0]
url=first_line.split(" ")[1]
http_pos=url.find("://")
if http_pos==-1:
temp=url
else:
temp=url[(http_pos+3):]
port_pos=temp.find(":")
webserver_pos=temp.find("/")
if webserver_pos == -1:
webserver_pos = len(temp)
webserver = ""
port = -1
if port_pos == -1 or webserver_pos < port_pos:
port = 80
webserver = temp[:webserver_pos]
else:
port = 80
#port = int(temp[(port_pos + 1):][:webserver_pos - port_pos -1])
webserver = temp[:port_pos]
proxy_server(webserver,port,Client,Request.encode(),addr)
except Exception as e:
print (e)
traceback.print_exc()
if __name__=="__main__":
try:
Server=CreateServer("",8888)
print("[*] Intializing socket. Done.")
print("[*] Socket binded successfully...")
print("[*] Server started successfully [{}]".format(8888))
except Exception as e:
print(e)
sys.exit(2)
while True:
try:
Client,addr,Request=ReadHTTPRequest(Server)
print("---------HTTP request: ")
print(Request)
_thread.start_new_thread(conn_string,(Client,Request,addr))
except KeyboardInterrupt:
Server.close()
print("\n[*] Shutting down..")
sys.exit()
Server.close()
[1]: https://i.stack.imgur.com/216ZO.png
您只是将原始请求转发到服务器,即在请求中包含完整的 URL:
GET http://ktdbcl.hcmus.edu.vn/ HTTP/1.1
Host: ktdbcl.hcmus.edu.vn
...
应该只转发路径:
GET / HTTP/1.1
Host: ktdbcl.hcmus.edu.vn
...
除此之外,请求和响应的读取严重中断。您没有正确解析 HTTP 协议,而是简单地等待一段时间并将几秒钟内没有数据视为消息结束。由于今天将通过同一个连接完成多个请求和响应,因此您的代码将严重减慢任何浏览速度。
与其等待多秒没有数据作为 request/response 结束标记,您应该正确解析 HTTP 协议并等待 HTTP 标准定义的适当的请求结束标记 - 请参阅 RFC 7230.
这是我在大学计算机网络课程研讨会上的代码。
要求:写一个代理网络服务器。从浏览器端口 8888 接收 HTTP 请求,并向 Web 服务器端口 80 发送 HTTP 请求。我似乎无法向 Web 服务器发送请求。
你能告诉我在这种情况下我的错误吗?
非常感谢
import socket
import sys
import _thread
import traceback
import ssl
def CreateServer(host, port):
Server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Server.bind((host,port))
Server.listen(5)
return Server
def ReadRequest(Client):
re = ""
Client.settimeout(10.0)
try:
re = Client.recv(1024).decode()
while (re):
re = re + Client.recv(1024).decode()
except socket.timeout: # fail after 1 second of no activity
if not re:
print("Didn't receive data! [Timeout]")
finally:
return re
#2. Client connect Server + 3. Read HTTP Request
def ReadHTTPRequest(Server):
re = ""
while (re == ""):
Client, address = Server.accept()
print("Client: ", address," da ket noi toi Server")
re = ReadRequest(Client)
return Client,address, re
def proxy_server(webserver, port, conn, data, addr):
print("{} {} {} {}".format(webserver, port, conn, addr))
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(10.0)
s.connect((webserver, port))
s.sendall(data)
while 1:
reply = s.recv(1024)
if len(reply) > 0:
conn.send(reply)
print("[*] Request sent: {} > {}".format(addr[0],webserver))
else:
break
s.close()
conn.close()
except Exception as e:
print(e)
traceback.print_exc()
s.close()
conn.close()
sys.exit(1)
def conn_string(Client,Request,addr):
try:
#print(addr)
first_line=Request.split('\n')[0]
url=first_line.split(" ")[1]
http_pos=url.find("://")
if http_pos==-1:
temp=url
else:
temp=url[(http_pos+3):]
port_pos=temp.find(":")
webserver_pos=temp.find("/")
if webserver_pos == -1:
webserver_pos = len(temp)
webserver = ""
port = -1
if port_pos == -1 or webserver_pos < port_pos:
port = 80
webserver = temp[:webserver_pos]
else:
port = 80
#port = int(temp[(port_pos + 1):][:webserver_pos - port_pos -1])
webserver = temp[:port_pos]
proxy_server(webserver,port,Client,Request.encode(),addr)
except Exception as e:
print (e)
traceback.print_exc()
if __name__=="__main__":
try:
Server=CreateServer("",8888)
print("[*] Intializing socket. Done.")
print("[*] Socket binded successfully...")
print("[*] Server started successfully [{}]".format(8888))
except Exception as e:
print(e)
sys.exit(2)
while True:
try:
Client,addr,Request=ReadHTTPRequest(Server)
print("---------HTTP request: ")
print(Request)
_thread.start_new_thread(conn_string,(Client,Request,addr))
except KeyboardInterrupt:
Server.close()
print("\n[*] Shutting down..")
sys.exit()
Server.close()
[1]: https://i.stack.imgur.com/216ZO.png
您只是将原始请求转发到服务器,即在请求中包含完整的 URL:
GET http://ktdbcl.hcmus.edu.vn/ HTTP/1.1
Host: ktdbcl.hcmus.edu.vn
...
应该只转发路径:
GET / HTTP/1.1
Host: ktdbcl.hcmus.edu.vn
...
除此之外,请求和响应的读取严重中断。您没有正确解析 HTTP 协议,而是简单地等待一段时间并将几秒钟内没有数据视为消息结束。由于今天将通过同一个连接完成多个请求和响应,因此您的代码将严重减慢任何浏览速度。
与其等待多秒没有数据作为 request/response 结束标记,您应该正确解析 HTTP 协议并等待 HTTP 标准定义的适当的请求结束标记 - 请参阅 RFC 7230.