2015-02-23 16 views
3

杉木让我清楚我不想使用更高级别的API,我只希望使用socket编程Python的套接字客户端后参数

我已经写了下面的程序使用POST请求连接到服务器。

import socket 
import binascii 

host = "localhost" 
port = 9000 
message = "POST /auth HTTP/1.1\r\n" 
parameters = "userName=Ganesh&password=pass\r\n" 
contentLength = "Content-Length: " + str(len(parameters)) 
contentType = "Content-Type: application/x-www-form-urlencoded\r\n" 

finalMessage = message + contentLength + contentType + "\r\n" 
finalMessage = finalMessage + parameters 
finalMessage = binascii.a2b_qp(finalMessage) 


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect((host, port)) 
s.sendall(finalMessage) 

print(s.recv(1024)) 

我在线检查了POST请求是如何创建的。

不知怎的,外观和数据没有得到传递给服务器。我需要在请求之间添加还是删除“\ r \ n”?

在此先感谢, 问候, Ganesh。

+0

这里的代码示例:使用套接字HTTPS POST请求做。(https://gist.github.com/zed/1841962# file-http-post-socket-py) – jfs 2015-02-23 11:45:27

回答

8

这行finalMessage = binascii.a2b_qp(finalMessage)肯定是错的,所以你应该完全删除行,另外一个问题是在Content-Length之后没有新行丢失。在这种情况下发送到插座的要求是(我在这里展示CRLF字符\r\n,同时也为清晰分割线):

POST /auth HTTP/1.1\r\n 
Content-Length: 31Content-Type: application/x-www-form-urlencoded\r\n 
\r\n 
userName=Ganesh&password=pass\r\n 

所以,很显然这并没有多大意义,Web服务器。


但是,即使添加新行和删除a2b_qp后,仍有问题是,你是不是talking HTTP/1.1存在;该请求必须具有HTTP/1.1(RFC 2616 14.23)一个Host头:

客户端必须在所有HTTP/1.1请求 消息的主机头字段。如果请求的URI不包括正被请求的服务的互联网主机名 ,那么Host头域必须是一个空值给出 。一个HTTP/1.1代理必须确保它不会转发任何 请求消息包含标识由代理所请求的服务的适当Host头 字段。 所有 基于因特网的HTTP/1.1服务器必须以400(错误请求) 状态码,其缺少Host头 字段中的任何HTTP/1.1请求消息进行响应。

而且你不支持分块请求和持久连接,保活什么的,所以你必须做Connection: close(RFC 2616 14.10):

HTTP /不支持持久连接1.1应用程序必须 包括每则消息中的“关闭”连接选项。

因此,任何HTTP/1.1服务器仍然会正常响应您的消息,但没有Host:标头也被破坏。

这是你应该发送到插座与该请求的数据:

POST /auth HTTP/1.1\r\n 
Content-Type: application/x-www-form-urlencoded\r\n 
Content-Length: 29\r\n 
Host: localhost:9000\r\n 
Connection: close\r\n 
\r\n 
userName=Ganesh&password=pass 

注意,你最好增加体内的\r\n了(因此主体29的长度)。此外,你应该阅读回应,以找出你得到的错误。


在Python 3中工作的代码会说:

host = "localhost" 
port = 9000 

headers = """\ 
POST /auth HTTP/1.1\r 
Content-Type: {content_type}\r 
Content-Length: {content_length}\r 
Host: {host}\r 
Connection: close\r 
\r\n""" 

body = 'userName=Ganesh&password=pass'         
body_bytes = body.encode('ascii') 
header_bytes = headers.format(
    content_type="application/x-www-form-urlencoded", 
    content_length=len(body_bytes), 
    host=str(host) + ":" + str(port) 
).encode('iso-8859-1') 

payload = header_bytes + body_bytes 

# ... 

socket.sendall(payload) 
+1

[http 0.9非常容易;]](http://askubuntu.com/a/525550/3712) – jfs 2015-02-23 11:48:59

+0

@Antti Haapala,非常感谢。这解决了我的问题。并请原谅我的HTTP知识。 还有一件事,那个调用binascii.a2b_qp()是必要的,因为套接字没有收到String作为输入。 – 2015-02-23 12:43:58

+0

Python 3?修复python 3的代码: – 2015-02-23 12:50:30