如何在Python中正确检测已关闭的套接字

时间:2014-06-24 04:37:05

标签: python json sockets http post

我有一个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()上阻止,直到服务器挂起?

1 个答案:

答案 0 :(得分:1)

netcat关闭连接,因为它的输入(例如你的python脚本)已经完成,因此netcat的stdin被关闭了。尝试向服务器发送HTTP请求的python脚本会挂起,因为使用HTTP时会出现几个错误:

  • 您将内容长度设置为len(body)+2,但它必须只是正文的长度,例如len(body)。这就是服务器仍在等待客户端数据的原因。
  • 您执行HTTP / 1.1请求但不处理您拥有的隐式保持活动,而是期望服务器关闭连接。你也不处理分块响应。

我建议使用http库来完成艰苦的工作,除非你渴望了解做HTTP的所有细节和陷阱。在这种情况下,我建议您先阅读规范,例如RFC2616(或更好:RFC7230..RFC7235)。

相关问题