Python套接字客户端Post参数

Gan*_*ute 6 python sockets post http

冷杉让我明白我不想使用更高级别的API,我只想使用套接字编程

我编写了以下程序,使用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))
Run Code Online (Sandbox Code Playgroud)

我在线检查了如何创建POST请求.

不知何故Paramters没有传递给服务器.我是否必须在请求之间添加或删除"\ r \n"?

在此先感谢,问候,Ganesh.

Ant*_*ala 10

这行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
Run Code Online (Sandbox Code Playgroud)

显然,这对Web服务器没有多大意义.


但即使在添加换行符并删除之后a2b_qp,仍然存在问题是你不是 HTTP/1.1那里说话 ; 请求必须具有HostHTTP/1.1(RFC 2616 14.23)的标头:

客户端必须在所有HTTP/1.1请求消息中包含Host头字段.如果请求的URI不包含所请求服务的Internet主机名,则必须为Host头字段指定一个空值.HTTP/1.1代理必须确保它转发的任何请求消息都包含一个适当的主机头字段,用于标识代理请求的服务.所有基于Internet的HTTP/1.1服务器必须以400(错误请求)状态代码响应任何缺少主机头字段的HTTP/1.1请求消息.

此外,您不支持分块请求和持久连接,Keepalive或任何东西,因此您必须这样做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
Run Code Online (Sandbox Code Playgroud)

请注意,您不再添加\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)
Run Code Online (Sandbox Code Playgroud)