2012-01-06 27 views
8

Tôi đang sử dụng kết nối socket trong PHP để đăng dữ liệu lên máy chủ web Apache. Tôi là một chút mới với kỹ thuật này, và tôi không chắc chắn làm thế nào để cô lập các tiêu đề từ cơ thể của phản ứng.Cách tách riêng phần đầu/thân HTTP khỏi yêu cầu Ổ cắm PHP

Mã Sending:

<?php 
// collect data to post 
$postdata = array(
    'hello' => 'world' 
); 
$postdata = http_build_query($postdata); 
// open socket, send request 
$fp = fsockopen('127.0.0.1', 80); 
fwrite($fp, "POST /server.php HTTP/1.1\r\n"); 
fwrite($fp, "Host: fm1\r\n"); 
fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n"); 
fwrite($fp, "Content-Length: ".strlen($postdata)."\r\n"); 
fwrite($fp, "Connection: close\r\n"); 
fwrite($fp, "\r\n"); 
fwrite($fp, $postdata); 
// go through result 
$result = ""; 
while(!feof($fp)){ 
    $result .= fgets($fp); 
} 
// close 
fclose($fp); 
// display result 
echo $result; 
?> 

server Code:

Hello this is server. You posted: 
<pre> 
<?php print_r($_POST); ?> 
</pre> 

Khi gửi bài đến một máy chủ, tôi nhận được:

HTTP/1.1 200 OK 
Date: Fri, 06 Jan 2012 09:55:27 GMT 
Server: Apache/2.2.15 (Win32) mod_ssl/2.2.15 OpenSSL/0.9.8m PHP/5.3.2 
X-Powered-By: PHP/5.3.2 
Content-Length: 79 
Connection: close 
Content-Type: text/html 

Hello this is server. You posted: 
<pre> 
Array 
(
    [hello] => world 
) 
</pre> 

Đúng như dự đoán. Tôi muốn loại bỏ các tiêu đề mặc dù, và chỉ cần đọc cơ thể từ "Xin chào đây là máy chủ ....." trở đi. Làm cách nào để phát hiện phần cuối của tiêu đề và đọc nội dung vào một biến?

Ngoài ra, máy chủ khác tôi đã thử nghiệm trên trả lời với điều này:

HTTP/1.1 200 OK 
Date: Fri, 06 Jan 2012 10:02:04 GMT 
Server: Apache/2 
X-Powered-By: PHP/5.2.17 
Connection: close 
Transfer-Encoding: chunked 
Content-Type: text/html 

4d 
Hello this is server. You posted: 
<pre> 
Array 
(
    [hello] => world 
) 
</pre> 
0 

là gì các "4d" và "0" xung quanh phần nội dung ??

Cảm ơn!

PS trước khi ai đó nói sử dụng CURL, tôi không thể không may :-(

+0

Không chắc về '4d' và '0', nhưng bạn có thể sử dụng' nổ (' \ r \ n \ r \ n ', $ result) 'khá đáng tin cậy. – Grexis

Trả lời

15

Bạn có thể tách các tiêu đề từ cơ thể bằng cách tách lên trên một linebreak đôi Nó phải là <CRLF><CRLF> vì vậy đây sẽ thường công việc:..

đáng tin cậy 10
list($header, $body) = explode("\r\n\r\n", $response, 2); 

hơn bạn nên sử dụng một regex để bắt biến linebreak (siêu không bao giờ xảy ra):

list($header, $body) = preg_split("/\R\R/", $response, 2); 

Điều với 4d0 được gọi là chunked encoding. (Đó là số thập phân được phân cách bằng một dấu ngắt dòng khác và cho biết độ dài của khối nội dung thô sau).

Để xóa điều đó, trước tiên bạn phải xem tiêu đề và xem có mục nhập theo số Transfer-Encoding: không. Điều này là nó trở nên phức tạp và được khuyến khích sử dụng một trong vô số các lớp xử lý HTTP của người dùng hiện có. PEAR has one.

+0

Tuyệt vời, phương pháp của bạn để phân tách các tiêu đề dường như hoạt động tốt. Ngoài ra, có vẻ như bạn đúng về các con số. Chúng thay đổi tùy theo độ dài của nội dung. Tôi ước mình có thể sử dụng CURL, tôi sẽ xem xét PEAR để xử lý nó .. Rất cám ơn! – Rob

0

Headers nên kết thúc với "\r\n\r\n" (hai lần). Những 4d và là có thể một phần của phản ứng php của bạn (họ không phải là một phần của tiêu đề)

+0

Cảm ơn, có vẻ như hoạt động – Rob

+0

Tại sao bỏ phiếu trên thực tế? : D – Rolice

0

Trong hầu hết các trường hợp, câu trả lời của Mario sẽ hoạt động nhưng tôi đã cố gắng áp dụng phương thức này để phản hồi từ Couch DB và có một số trường hợp khi nó không hoạt động.

Nếu phản hồi không chứa bất kỳ tài liệu nào thì Couch DB đặt "\ r \ n \ r \ n" bên trong nội dung phản hồi cố gắng giữ kết quả tốt và trong trường hợp này không đủ để chỉ phân tách phản hồi bằng \ r \ n \ r \ n "vì bạn có thể vô tình cắt phần cuối của cơ thể.

HTTP/1.0 200 OK Server: CouchDB/1.6.1 (Erlang OTP/R16B02) ETag: "DJNMQO5WQIBZHFMDU40F1O94T" Date: Mon, 06 Jul 2015 09:37:33 GMT Content-Type: text/plain; charset=utf-8 Cache-Control: must-revalidate 
{"total_rows":0,"offset":0,"rows":[ 
// Couch DB adds some extra line breakers on this line 
]} 

Tiếp theo phân tích cú pháp có vẻ là đáng tin cậy hơn cho Couch DB:

$parts = explode("\r\n\r\n", $response); 

if ($parts) 
{ 
    $headers = array_shift($parts); 
    $body = json_decode(implode("\r\n\r\n", $parts)); 
} 
+0

FWIW: Câu trả lời của anh ta vẫn sẽ làm việc cho bạn. Khóa là "2" trong tham số thứ ba của 'phát nổ'. Có nghĩa là Sẽ chỉ có tối đa 2 mục trong một mảng được tạo bằng 'phát nổ'. Vì vậy, trong 'list ($ header, $ body)', "chunk" đầu tiên của mảng sẽ được gán cho '$ headers', và mọi thứ khác, bất kể có bao nhiêu' \ r \ n' tồn tại, sẽ được gán thành '$ body'. – Oberst

Các vấn đề liên quan