使用scoket发送HTTP请求

建议先看一下如何用telnet发送HTTP请求:
http://blog.csdn.net/whd526/article/details/75042691

http.class.php

<?php
class Http{

    const CRLF = "\r\n";
    protected $errno = -1;
    protected $errstr = '';


    protected $url = null;
    protected $version = 'HTTP/1.1';
    protected $fh = null;

    protected $line = array();
    protected $header = array();
    protected $body = array();

    protected $response = '';

    public function __construct($url){
        $this->conn($url);
        $this->setHeader('Host',$this->url['host']);
    }

    /**
    *此方法负责写请求行
    *如 GET /index.php HTTP/1.1
    */
    private function setLine($method){
        $this->line[0] = $method.' '.$this->url['path'].$this->url['query'].' '.$this->version;
    }
    /**
    *此方法负责写头信息
    *如Host: localhost
    */
    public function setHeader($key,$value){
        $this->header[] = $key.': '.$value;
    }

    /**
    *此方法负责写POST主体信息
    *key=value的形式写进数组
    *用http_build_query()封装成key1=value1&key2=value2
    */
    public function setBody($key,$value){
        //$this->body[] = $key.'='.$value;
        $this->body[$key] = $value;
    }

    /**
    *用fsockopen打开网络连接
    *就像telnet 192.168.0.0 80
    */
    private function conn($url){
        //parse_url解析地址,返回其组成部分
        $this->url = parse_url($url);

        //如果URL没有port,则默认80端口
        if(!isset($this->url['port'])){
            $this->url['port'] = '80';
        }

        //如果URL没有path,则默认根路径'/'
        //如www.baidu.com没有path
        //如http://news.baidu.com/sports,path为/sports
        if(!isset($this->url['path'])){
            $this->url['path'] = '/';
        }

        if(!isset($this->url['query'])){
            $this->url['query'] = '';
        }else{
            $this->url['query'] = '?'.$this->url['query'];
        }

        //打开网络连接
        $this->fh = fsockopen($this->url['host'],$this->url['port'],$this->errno,$this->errstr,3);
        if(!$this->fh){
            echo "ERROR:$errno-$errstr";
            exit;
        }
    }

    public function get(){
        $this->setLine('GET');
        $this->body='';
        $this->request();
        return $this->response;
    }

    public function post(){
        $this->setLine('POST');
        $this->setHeader('Content-type','application/x-www-form-urlencoded');

        $this->body = http_build_query($this->body);
        //var_dump($this->body);exit();
        $this->setHeader('Content-length',strlen($this->body));
        $this->request();
        return $this->response;
    }

    /**
    *拼接请求信息,并写入response
    */
    private function request(){
        $req = array_merge($this->line,$this->header,array(''),array($this->body),array(''));
        //var_dump($req);exit;
        $req = implode(self::CRLF,$req);
        //print_r($req);exit;
        fwrite($this->fh, $req);
        while(!feof($this->fh)){
            $this->response .= fread($this->fh, 1024);
        }
        $this->close();
    }

    /**
    *关闭socket连接
    */
    public function close(){
        fclose($this->fh);
    }
}
//GET请求
// $url = 'http://www.baidu.com';
// $http = new Http($url);
// $http->setHeader('Connection','close');
// echo $http->get();

//POST请求
// $url = 'http://localhost/tel2.php';
// $http = new Http($url);
// $http->setHeader('Connection','close');
// $http->setBody('username','Edward');
// $http->setBody('age','20');
// $http->setBody('submit','提交');
// echo $http->post();
?>

为什么要在头信息设置Connection:close
如果不设置Connection:close,会发现速度非常慢,feof不能准确判断是否已经得到了所有的数据,直到超过设置的超时时间才结束。

Connection的状态有两种,一种是keep-alive 另外一种就是close。
keep-alive就是保持客户端与服务器的连接,这是默认的方式。
close表示服务器给客户端发送信息之后就断开了,.close对资源消耗占用的少一些。
再完善一点,其实这和TCP三次握手有关,如果返回的是keep-alive表示之前的握手还可以用在接下来的请求当中去,如果是close的话当前请求完成后会进行四次握手关闭连接,在接下来的请求就要重新握手,这是HTTP/1.1相对1.0新增的一个部分,加快了网络传输。

实战:
用HTTP请求,往电驴发送站内信(http://home.verycd.com/cp.php?ac=pm
先注册登录,然后在线发送一遍,用谷歌浏览器的开发者模式观察请求头信息,至于具体的抓包细节就不一一赘述了

<?php
require('./http.class.php');
$url = 'http://home.verycd.com/cp.php?ac=pm&op=send&touid=0&pmid=0';
$http = new Http($url);
$http->setHeader('Connection','close');
$http->setHeader('Accept','text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8');
$http->setHeader('Accept-Encoding','gzip, deflate');
$http->setHeader('Accept-Language','zh-CN,zh;q=0.8');

$http->setHeader('Cookie','xxxx');//自己的cookie
$http->setHeader('Referer','http://home.verycd.com/cp.php?ac=pm&op=send&touid=0&pmid=0');
$http->setHeader('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36');
$http->setBody('username','test');
$http->setBody('message','robot2222');
$http->setBody('refer','');
$http->setBody('pmsubmit','true');
$http->setBody('pmsubmit_btn','发送');
$http->setBody('formhash','16f835b2');

$http->post();
echo "ok";
?>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值