使用 python 脚本向带有 netcat 的服务器发送 GET 请求

Using python script to send GET request to a server with netcat

我是 运行ning Ubuntu 16.04,我正在尝试编写一个 python 脚本,在给定 [=66= 的情况下向指定的图像文件发出 GET 请求].例如,在下面的代码中:

hostwww.google.com

port80

u.path/images/srpr/logo3w.png

proc = Popen(["netcat {} {}".format(host, port)], shell= True)
proc = Popen(["GET {} HTTP/1.1".format(u.path)], shell= True)
proc = Popen(["Host: {}".format(host)], shell= True)
proc = Popen(["Connection: close"], shell= True)
proc = Popen(["\n"], shell= True)

我的问题是我可以在终端中正常执行这些,但是当我尝试 运行 脚本时,它似乎在它需要之前将 GET 请求发送到 www.google.com u.path 的规范。我知道这样做有两个原因。首先,就在服务器响应到来之前,我得到以下信息:

/bin/sh: 1: Host:: not found /bin/sh: 1: Connection:: not found

其次,我知道图像数据的服务器响应是一堆丑陋的东西,在终端上被解释为奇怪的 Unicode 符号,但我显然得到了 www.google.com HTML 文本在服务器响应上。

我想我可能需要让它等待 HTTP 请求,直到 netcat STDIN 打开,但我不知道如何做。或者它只是完成了请求,因为它以某种方式发送了 \n?我真的不知道。

编辑:看起来它实际上并没有向 www.google.com 发送请求。我将服务器响应保存为 .html 文件,它看起来像一个云端网站

EDIT2:经过更多的研究,问题似乎是因为 netcat 是交互式的,所以它 'deadlocks' 或类似的东西。我尝试使用 proc.communicate() 但由于我需要发送多行它不允许它看到 communicate 只允许将初始输入写入 STDIN 然后它发送 EOF 或类似的东西。这导致我尝试使用 proc.stdin.write 但这显然也已知会导致与使 Popen 命令对 STDIN、[=35= 使用 subprocess.PIPE 有关的事情发生死锁],以及 STDERR。它还要求将输入编码为 bytes-like 对象,我已经完成了,但是当我在最后发送 \r\n\r\n 以尝试关闭连接时,它什么也没做, STDOUT 只包含 b'' 我理解为 bytes

形式的空字符串

对于遇到类似问题的任何人,这是我找到的解决方案:

#begin the interactive shell of netcat
proc = Popen(['netcat -q -1 {} {}'.format(host, port)], shell=True, stdout=PIPE, stdin=PIPE, stderr=PIPE)

#set file status flags on stdout to non-blocking reads
fcntl.fcntl(proc.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)

#each time we write a diffrent line to the interactive shell
#we need to flush the buffer just to be safe
#credit to http://nigelarmstrong.me/2015/04/python-subprocess/
proc.stdin.write(str.encode('GET %s HTTP/1.1\n' %(path+filename)))
proc.stdin.flush()
proc.stdin.write(str.encode('Host: {}\n'.format(host)))
proc.stdin.flush()
proc.stdin.write(str.encode('Connection: close\n'))
proc.stdin.flush()
proc.stdin.write(str.encode('\r\n\r\n'))
proc.stdin.flush()

#give the server time to respond
proc.wait()

#store the server response (which is bytes-like)
#attempting to decode it results in error since we're recieving data as a mix of text/image
serv_response = proc.stdout.read()