2015-02-23 44 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