我有一个python脚本,它发出一个带有json主体的HTTP POST
,我管道到netcat
并且一切正常:
#!/usr/bin/python
body = "{ \"key\": \"Test\", \"value\": \"Test\" }"
print "POST /valSet HTTP/1.1\r"
print "Host: 192.168.10.1\r"
print "Content-Type: application/json\r"
print "Accept: application/json\r"
print "Content-Length: " + str(len(body)+2) + "\r"
print "\r"
print body
$ ./valSet | nc 192.168.10.1 80
HTTP/1.1 200 OK
Server: Innovix
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json
e
{"success": 0}
0
$
如上所示,HTTP
代码已发送,netcat
将其转发到端口80,响应成功。更重要的是,在分块响应中出现最后0
后,连接会立即终止。
然而,在我的环境中,我不能依赖netcat
在那里,所以我需要一个自包含的程序。因此,我重写了以上内容:
def set():
key = raw_input("Key: ")
val = raw_input("Value: ")
body = "{ \"key\": \"" + key + "\", \"value\": \"" + val + "\" }"
send(body)
def send(body):
s.send("POST /valSet HTTP/1.1\r\n")
s.send("Host: " + SERVER_IP + "\r\n")
s.send("Content-Type: application/json\r\n")
s.send("Accept: application/json\r\n")
s.send("Content-Length: " + str(len(body)+2) + "\r\n")
s.send("\r\n")
s.send(body)
# Get response
while True:
data = s.recv(1024)
print 'Response:', data
if not data:
break
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((SERVER_IP, SERVER_PORT))
set()
这又有效,但有一个严重的缺点:recv()
执行两次,然后挂起。在服务器端,它最终会超时Client timed out; closing socket
。
问题:为什么netcat
版本会立即终止,我的python版本会在recv()
上阻止,直到服务器挂起?
答案 0 :(得分:1)
netcat关闭连接,因为它的输入(例如你的python脚本)已经完成,因此netcat的stdin被关闭了。尝试向服务器发送HTTP请求的python脚本会挂起,因为使用HTTP时会出现几个错误:
len(body)+2
,但它必须只是正文的长度,例如len(body)
。这就是服务器仍在等待客户端数据的原因。我建议使用http库来完成艰苦的工作,除非你渴望了解做HTTP的所有细节和陷阱。在这种情况下,我建议您先阅读规范,例如RFC2616(或更好:RFC7230..RFC7235)。