[ arsa xx @ 25.01.2004. 15:01 ] @
S obzirom da nisam nasao adekvatnu klasu napisao sam jednu malu funkciju koja radi i zavrsava posao. Jedino nisam siguran u nju pa pa ko poznaje problematiku moze da pomogne.

Preuzimanje requesta sam raslanio na cetri slucaja

1. Kada imamo u header Content-Lenght: xxx
$data=my_fgets(Content-Lenght)

2. Kada imamo Connestion:colose
while (!feof($this->fp)) {
$data .= fgets($this->fp, 1024);
}
3. Kada je Transfer-Encoding: chunked
za sve chunk-ove{
$data.=my_fgets(chunk_lenght)
}
4. Kada server posalje status kode 100, data jednostavno nastavimo sa citanjem sledeceg headera(krenemo od tacke 1)

najvazniji deo je funkcija koju sam napisao, za nju su mi potrebni saveti, resenja jer nisam 100% siguran dali je dobra za sve situacije.Doduse probao sam oko 15-tak sajtova i sve strane su ispravno skinute.

Code:

    function my_fgets($data_length){
        $rest_length=$data_length;
        while ($rest_length>0){   //!feof($this->fp) feof() neradi posao
            $line_length=min(1024,$rest_length);
            $my_data .= fread($this->fp, $line_length);
            $rest_length=$data_length-strlen($my_data);

            $status=socket_get_status($this->fp);
            if($status[time_out]==true){break;}
        } 

        return $my_data;
    }


umesto ove funksije u klasama koje sam nalazio se koristi fread(), ali desavalo se da ne procita zadatu duzinu nego samo deo, dok gornja funksija dobro radi.



evo i dela koda
Code:

        if ($this->incoming_headers['connection'] == 'close') {
            $this->debug('Slucaj 1');
            while (!feof($this->fp)) {
                $data .= fgets($this->fp, 1024);
            }
        }

        else if (isset($this->incoming_headers['content-length']) and 
                strpos($this->incoming_headers['transfer-encoding'], 'chunked') === false) {
            $this->debug('Slucaj 2, <br>Content-Length:'.$this->incoming_headers['content-length']);

            //$data = fread($this->fp,$this->incoming_headers['content-length']);
            
            $data = $this->my_fgets($this->incoming_headers['content-length']);
        }
        else if(trim($this->incoming_headers['transfer-encoding']) == 'chunked'){
            $this->debug('Slucaj 3');
            // chunked encoding
            $length = fgets($this->fp, 1024);
            $length = hexdec($length);
            //echo $length."<br>";
            while (true) {
                if ($length == 0) { break; }
                
                $data .= $this->my_fgets($length);
                $total_lenght+=$length;
                fgets($this->fp, 1024);
                $length = fgets($this->fp, 1024);
                $length = hexdec($length);
            }  
            //echo "<hr>".$total_lenght."<hr>";
        }
[ bzero @ 26.01.2004. 10:19 ] @
Savetujem ti da umesto HTTP/1.1 koristis HTTP/1.0 i olaksas sebi zivot, posto u vecini slucajeva nema potrebe iz php-a koristiti noviju verziju protokola.
Ukoliko ipak iz nekog razloga moras da koristis HTTP/1.1 procitaj specifikaciju protokola i ako je pazljivo primenis radice bez problema.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
[ leka @ 26.01.2004. 10:54 ] @
http://nanoweb.si.kz/ , skines sors i ucis iz njega.
[ arsa xx @ 26.01.2004. 18:25 ] @
Ako se pazljivije pogleda moj post vidi se da je to jezgro resenja problema PRIHVATA HTTP/1.1 odgovora.

@zombie

Jasno je totalno da je HTTP/1.0 laksi za prihvat.
HTTP/1.1 sam proucio dovoljno da is toga sam izvukao gornje slucajeve.
Naravno drugi deo klase obradjuje slucajeve kada postoji redirekcija.

@leka

nanoweb je HTTP/1.1 server i nevidim nista slicno ovome sto sam radio,
posto je server a ujedno i ne koristi fsockopen() nista ne mogu prilagoditi.

Meni treba klijent koji ce da prihvati HTTP/1.1 request
Sve imam gotovo samo me muce sledeca dva.

1. fread() funkcija ne procita nekad zadatu duzinu, zasto?
2. Funkcija donja resava taj problem, samo da li postoli u njoj neki propust?
Jer hocu da budem siguran da je to to.

Mislim da je funkcija dovoljno jasna da netreba neka dodatna objasnjenja.

// Ime: my_fgets(lenght)
// Opis: Vraca string zadate duzine lenght

Code:
function my_fgets($data_length){
    $rest_length=$data_length;
    while ($rest_length>0){
        $line_length=min(1024,$rest_length);
        $my_data .= fread($this->fp, $line_length);
        $rest_length=$data_length-strlen($my_data);
        $status=socket_get_status($this->fp);
        if($status[time_out]==true){break;}
    } 
    return $my_data;
}
[ -zombie- @ 28.01.2004. 04:59 ] @
ne znam gde si video da sam ti ja išta rekao? ;)

mada, možda si to umislio, zato što si pretpostavio da ću ja reći nešto slično: najverovatnije ti ne treba da šalješ http/1.1 zahteve, pa samim tim ne postoji ni problem oko prijema http/1.1 odgovora, ne? ako ti baš izričito trebaju, baš bih voleo da znam konkretan razlog..

inače, funkcija ti je ok. malo je nezgrapno napisana (stvar ukusa) ali je logika ispravna, i trebala bi da radi. samo još mala preporuka, mogao bi da je nazoveš my_fread() pošto ipak više oponaša fread() funkciju a ne fgets() ;)

a i btw, nije mi baš apsolutno jasno zašto fread() ne bi radila. ja sam je dosta koristio, i nisam naišao na probleme koje ti opisuješ.. da greška nije bila u nečemu drugom. ili da jednostavno nisi imao problema sa mrežom? (što ti tvoja funkcija takođe neće rešiti..)
[ arsa xx @ 28.01.2004. 13:54 ] @
Bas je u tome stvar sto resava. fread() jednostavno neprocita zadati broj bajtova.
Npr.:
echo strlen(fread($fp,4096)); // dobijem npr. 2096
dok sa mojom funkcijom dobijem output nesto kao:

2096
1000
900
100
-------
=4096

znaci jednostavno cita dok neprocita sve.

Naziv je vec promenjen :) +napisao sam celu klasu :)

Razlog: Sa HTTP/1.1 mogu da ostvarujem i perzistent konekciju ;)

Evo i nove finkcije kako izgleda sa doradom za provere:
Code:

function my_fread($data_length){
    $rest_length=$data_length;
    while ($rest_length>0){ 
        $line_length=min(1024,$rest_length);
        $data_line = fread($this->fp, $line_length);
        $my_data .= $data_line;
        $rest_length=$data_length-strlen($my_data);
        if($this->_socket_time_out() || $this->_check_traffic_limit(strlen($data_line))){
            $this->read_break=true;
            break;
        }
    } 
    return $my_data;
}


Pitam se samo dali je potrebna ova linija:
Code:

$line_length=min(1024,$rest_length);
[ -zombie- @ 07.02.2004. 13:28 ] @
dok sam radio nešto drugo, pade mi na pamet da ti nemaš možda mod socket_set_nonblock() uključen, ili neku sličnu opciju..

to je jedini razlog zbog koga bi funkcija vraćala manje bajtova nego što joj ti zatražiš. znači, u trenutku kada je pozoveš, stiglo je samo par stotina bajtova, a pošto je u non-blocking modu, ona ne čeka da stigne i ostalo, nego ti odma vrati sve što ima. ;)

proveri da nije to. pogledaj i socket_get_status(), socket_get_option() i srodne funkcije..