Maison  >  Article  >  développement back-end  >  Explication détaillée de la façon dont PHP utilise le socket pour envoyer des requêtes HTTP

Explication détaillée de la façon dont PHP utilise le socket pour envoyer des requêtes HTTP

*文
*文original
2018-01-05 10:10:142078parcourir

En tant que programmeur PHP, vous serez certainement exposé au protocole http. Ce n'est qu'en ayant une compréhension approfondie du protocole http que votre niveau de programmation pourra s'améliorer. Récemment, j'ai découvert la programmation HTTP en PHP. Beaucoup de choses sont devenues claires pour moi et j'en ai beaucoup bénéficié. J'espère le partager avec tout le monde. Cet article doit être lu par les développeurs possédant une certaine base http. J'espère que cela aide tout le monde.

Aujourd'hui, je vais vous montrer comment utiliser socket pour envoyer des requêtes GET et POST.

Dans la programmation quotidienne, je crois que beaucoup de gens, comme moi, utilisent le navigateur pour faire des requêtes GET et POST au serveur la plupart du temps. Alors, puis-je utiliser d'autres méthodes pour faire des requêtes GET et POST ? La réponse doit être oui. Quiconque connaît le protocole HTTP sait que l'essence du navigateur soumettant une requête est d'envoyer des informations de requête au serveur. Ces informations de requête se composent d'une ligne de requête, d'un en-tête de requête et d'un corps de requête (facultatif). Le serveur renvoie des informations de réponse sur la base des informations de demande. La connexion est perdue.

Le format de la requête HTTP est le suivant :

<request-line>
<headers>
<blank line>
[<request-body>]

Le format de la réponse HTTP est très similaire au format de la requête :

<status-line>
<headers>
<blank line>
[<response-body>]

Nous pouvons utiliser HTTP pour envoyer des requêtes. Principe, vous pouvez reconsidérer l'utilisation de socket pour envoyer des requêtes HTTP.

La signification anglaise originale de Socket est "hole" ou "socket". Également communément appelé « socket », il est utilisé pour décrire une adresse IP et un port. Il s'agit d'un handle vers une chaîne de communication et peut être utilisé pour mettre en œuvre la communication entre différentes machines virtuelles ou différents ordinateurs. Les hôtes sur Internet exécutent généralement plusieurs logiciels de services et fournissent plusieurs services en même temps. Chaque service ouvre un Socket et est lié à un port. Différents ports correspondent à différents services. De ce point de vue, il est en fait aussi simple d'utiliser des sockets pour faire fonctionner des fichiers distants que pour lire et écrire des fichiers locaux. Considérez les fichiers locaux comme étant transmis via le matériel, et les fichiers distants tant qu'ils sont transmis via des câbles réseau.

Par conséquent, l'envoi d'une requête peut être considéré comme l'établissement d'une connexion->ouvrir l'interface socket (fsockopen())->demande d'écriture (fwrite())->lire la réponse (fread()- > ; Fermez le fichier (fclose()). Sans plus tarder, passons directement au code :

<?php 
interface Proto {
  // 连接url
  function conn($url);
  //发送get查询
  function get();
  // 发送post查询
  function post();
  // 关闭连接
  function close();
}
class Http implements Proto {
  const CRLF = "\r\n";
  protected $errno = -1;
  protected $errstr = &#39;&#39;;
  protected $response = &#39;&#39;;
  protected $url = null;
  protected $version = &#39;HTTP/1.1&#39;;
  protected $fh = null;
  protected $line = array();
  protected $header = array();
  protected $body = array();
  public function __construct($url) {
    $this->conn($url);
    $this->setHeader(&#39;Host: &#39; . $this->url[&#39;host&#39;]);
  }
  // 此方法负责写请求行
  protected function setLine($method) {
    $this->line[0] = $method . &#39; &#39; . $this->url[&#39;path&#39;] . &#39;?&#39; .$this->url[&#39;query&#39;] . &#39; &#39;. $this->version;
  }
  // 此方法负责写头信息
  public function setHeader($headerline) {
    $this->header[] = $headerline; 
  }
  // 此方法负责写主体信息
  protected function setBody($body) {
     $this->body[] = http_build_query($body);
  }
  // 连接url
  public function conn($url) {
    $this->url = parse_url($url);
    // 判断端口
    if(!isset($this->url[&#39;port&#39;])) {
      $this->url[&#39;port&#39;] = 80;
    }
    // 判断query
    if(!isset($this->url[&#39;query&#39;])) {
      $this->url[&#39;query&#39;] = &#39;&#39;;
    }
    $this->fh = fsockopen($this->url[&#39;host&#39;],$this->url[&#39;port&#39;],$this->errno,$this->errstr,3);
  }
  //构造get请求的数据
  public function get() {
    $this->setLine(&#39;GET&#39;);
    $this->request();
    return $this->response;
  }
  // 构造post查询的数据
  public function post($body = array()) {   
    $this->setLine(&#39;POST&#39;);
    // 设计content-type
    $this->setHeader(&#39;Content-type: application/x-www-form-urlencoded&#39;);
    // 设计主体信息,比GET不一样的地方
    $this->setBody($body);
    // 计算content-length
    $this->setHeader(&#39;Content-length: &#39; . strlen($this->body[0]));
    $this->request();
    return $this->response;
  }
  // 真正请求
  public function request() {
    // 把请求行,头信息,实体信息 放在一个数组里,便于拼接
    $req = array_merge($this->line,$this->header,array(&#39;&#39;),$this->body,array(&#39;&#39;));
    //print_r($req);
    $req = implode(self::CRLF,$req); 
    //echo $req; exit;
    fwrite($this->fh,$req);
    while(!feof($this->fh)) {
      $this->response .= fread($this->fh,1024);
    }
    $this->close(); // 关闭连接
  }
  // 关闭连接
  public function close() {
    fclose($this->fh);
  }
}

Utilisez cette classe pour envoyer une simple requête GET :

<?php
//记得引用Http类
$url="http://home.***.net/u/DeanChopper/";
$http=new Http($url);
$response=$http->get();
print_r($response);

La valeur de retour est information , vous pouvez traiter davantage les informations de réponse pour obtenir le contenu souhaité

Regardons l'exemple spécifique suivant

<?php
/**
 * 使用PHP Socket 编程模拟Http post和get请求
 * @author koma
 */
class Http{
  private $sp = "\r\n"; //这里必须要写成双引号
  private $protocol = &#39;HTTP/1.1&#39;;
  private $requestLine = "";
  private $requestHeader = "";
  private $requestBody = "";
  private $requestInfo = "";
  private $fp = null;
  private $urlinfo = null;
  private $header = array();
  private $body = "";
  private $responseInfo = "";
  private static $http = null; //Http对象单例
   
  private function __construct() {}
   
  public static function create() {
    if ( self::$http === null ) { 
      self::$http = new Http();
    }
    return self::$http;
  }
   
  public function init($url) {
    $this->parseurl($url);
    $this->header[&#39;Host&#39;] = $this->urlinfo[&#39;host&#39;];
    return $this;
  }
   
  public function get($header = array()) {
    $this->header = array_merge($this->header, $header);
    return $this->request(&#39;GET&#39;);
  }
   
  public function post($header = array(), $body = array()) {
    $this->header = array_merge($this->header, $header);
    if ( !empty($body) ) {
      $this->body = http_build_query($body);
      $this->header[&#39;Content-Type&#39;] = &#39;application/x-www-form-urlencoded&#39;;
      $this->header[&#39;Content-Length&#39;] = strlen($this->body);
    }
    return $this->request(&#39;POST&#39;);
  }
   
  private function request($method) {
    $header = "";
    $this->requestLine = $method.&#39; &#39;.$this->urlinfo[&#39;path&#39;].&#39;?&#39;.$this->urlinfo[&#39;query&#39;].&#39; &#39;.$this->protocol;
    foreach ( $this->header as $key => $value ) {
      $header .= $header == "" ? $key.&#39;:&#39;.$value : $this->sp.$key.&#39;:&#39;.$value;
    }
    $this->requestHeader = $header.$this->sp.$this->sp;
    $this->requestInfo = $this->requestLine.$this->sp.$this->requestHeader;
    if ( $this->body != "" ) {
      $this->requestInfo .= $this->body;
    }
    /*
     * 注意:这里的fsockopen中的url参数形式为"www.xxx.com"
     * 不能够带"http://"这种
     */
    $port = isset($this->urlinfo[&#39;port&#39;]) ? isset($this->urlinfo[&#39;port&#39;]) : &#39;80&#39;;
    $this->fp = fsockopen($this->urlinfo[&#39;host&#39;], $port, $errno, $errstr);
    if ( !$this->fp ) {
      echo $errstr.&#39;(&#39;.$errno.&#39;)&#39;;
      return false;
    }
    if ( fwrite($this->fp, $this->requestInfo) ) {
      $str = "";
      while ( !feof($this->fp) ) {
        $str .= fread($this->fp, 1024);
      }
      $this->responseInfo = $str;
    }
    fclose($this->fp);
    return $this->responseInfo;
  }
   
  private function parseurl($url) {
    $this->urlinfo = parse_url($url);
  }
}
// $url = "http://news.***.com/14/1102/01/AA0PFA7Q00014AED.html";
$url = "http://localhost/httppro/post.php";
$http = Http::create()->init($url);
/* 发送get请求 
echo $http->get(array(
  &#39;User-Agent&#39; => &#39;Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36&#39;,
));
*/
 
/* 发送post请求 */
echo $http->post(array(
    &#39;User-Agent&#39; => &#39;Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36&#39;,
), array(&#39;username&#39;=>&#39;发一个中文&#39;, &#39;age&#39;=>22));

Recommandations associées. :

Explication détaillée de la fonction de modification des autorisations de fichier de PHP chmod

Explication détaillée de la façon dont PHP implémente le Mécanisme de hook

Explication détaillée de l'utilisation de PHP pour trouver la sous-chaîne commune la plus longue de deux chaînes

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn