[PHP/MySQL] Simultane verbindingen van een client gaat niet?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • djbe
  • Registratie: Juni 2005
  • Laatst online: 13-06 03:43
Hallo tweakers,

Ik had een vraagje betreffend php en mysql:
Via het bestand dl.php kan een bestand afgehaald worden. Tijdens het downloaden worden de stats bijgehouden in een mysql database. Via een ander bestand, getReport.php, kan men de stats bekijken voor die download (als die er is). Het probleem is dat, wanneer de download bezig is, en ik ondertussen (in een andere tab/window) getReport.php oproep, dan blijft die wachten tot dl.php gedaan heeft eer dat die iets terug geeft. Het is alsof 2 verbindingen vanuit dezelfde pc niet gaat...

Ik wil jullie niet opzadelen met een hele hoop code, dus zal maar de betreffende bestanden posten:
dl.php:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php

require('inc_path.php');
require(INC_DIR . 'global_vars.php');
require(INC_DIR . 'downloadsDB.php');
//
// Send a file
//
function send_file($sID, $path, $name) {
    $status = FALSE;
    
    // say we are connecting
    updateSession($sID, '123', 'connecting', '0', '');
    
    if (!is_file($path . $name) or connection_status() != 0)
        return FALSE; // a connection_status of 0 means NORMAL
    
    header('Content-Type: application/octet-stream; name="' . $name . '"'); //This should work for Non IE/Opera browsers
    header('Content-Type: application/octetstream; name="' . $name . '"'); // This should work for IE & Opera
    header("Content-Disposition: attachment; filename=\"" . $name . "\"");
    header('Content-length: ' . (string) (filesize($path.$name)));
    header('Cache-Control: no-cache, must-revalidate');
    header('Pragma: no-cache');
    header('Expires: ' . gmdate('D, d M Y H:i:s', mktime(date('H') + 2, date('i'), date('s'), date('m'), date('d'), date('Y'))) . ' GMT');
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
    
    if ($file = fopen($path . $name, 'rb')) {
        $i = 0;
        $total = filesize($path.$name);
        
        while (!feof($file) and (connection_status() == 0)) {
            updateSession($sID, '123', 'transferring', (int) ((float) $i * 100 / $total), '');
            print(fread($file, 1024 * 8));
            flush();
            $i += 1024 * 8;
        }
        
        $status = (connection_status() == 0);
        fclose($file);
    }
    
    updateSession($sID, '123', 'complete', 100, '');
    
    return($status);
}
//
// Module body
//
session_start();
$sID = session_id();
session_write_close();

$connection = connectToDatabase();

if (!send_file($sID, '../../', 'archief.exe')) {
    die ('File Transfer Failed');
} else {
    // File sent ok - log it
}

mysql_close($connection);

?>


getReport.php:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php

///////////////////////////////////////////////////////////////////////////////
//                  Get XML report                              //
///////////////////////////////////////////////////////////////////////////////
//
//
//
// Includes
//

require('inc_path.php');
require(INC_DIR . 'global_vars.php');
require(INC_DIR . 'downloadsDB.php');
//
// Print XML
//
function printXml($fileName, $status, $progress, $queue) {
    header('Content-Type: text/xml');
    echo('<?xml version="1.0" encoding="UTF-8"?>' . "\n");
    echo('<as-download>' . "\n");
    echo("\t" . '<filename>' . $fileName . '</filename>' . "\n");
    echo("\t" . '<status>' . $status . '</status>' . "\n");
    echo("\t" . '<progress>' . $progress . '</progress>' . "\n");
    for ($i = 0; $i < count($queue); $i++)
        echo("\t" . '<queue>' . $queue[$i] . '</queue>' . "\n");
    echo('</as-download>');
}
//
// an xml with an error message
//
function printErrorXml($message) {
    header('Content-Type: text/xml');
    echo('<?xml version="1.0" encoding="UTF-8"?>' . "\n");
    echo('<as-download>' . "\n");
    echo("\t" . '<error>' . $message . '</error>' . "\n");
    echo('</as-download>');
}
//
// Function calls 
//
session_start();
$session_id = session_id();
session_write_close();

$connection = connectToDatabase();

if (getSessionData($session_id, &$fileID, &$status, &$progress, &$queue))
    printXml($fileID, $status, $progress, $queue);
else
    printErrorXml('no results!');

mysql_close($connection);

?>


downloadsDB.php:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?php

function connectToDatabase() {
    $dbh = mysql_connect(DATABASE_SERVER, DATABASE_USER, DATABASE_PASS) or
        die('Could not connect to database because: ' . mysql_error());
        
    @mysql_select_db(DATABASE_NAME) or
        die('Unable to select database: ' . mysql_error());
        
    return $dbh;
}

function updateSession($sessionID, $fileID, $status, $progress, $queue) {
    $query = "SELECT * FROM `" . DOWNLOADS_TABLE . "` WHERE sessionID='$sessionID'";
    $result = mysql_query($query);
    
    $query = NULL;
    if (mysql_affected_rows() < 1) {
        $query = "INSERT INTO `" . DOWNLOADS_TABLE . "` (sessionID, fileID, status, progress, queue) VALUES ('$sessionID', '$fileID', '$status', '$progress', '$queue')";
    } else if (
        $fileID != mysql_result($result, 0, 'fileID') ||
        $status != mysql_result($result, 0, 'status') ||
        $progress != mysql_result($result, 0, 'progress') ||
        $queue != mysql_result($result, 0, 'queue')
        ) {
        $query = "UPDATE `" . DOWNLOADS_TABLE . "` SET fileID='$fileID', status='$status', progress='$progress', queue='$queue' WHERE sessionID='$sessionID'";
    }
    
    mysql_query($query);
}

function getSessionData($sessionID, &$fileID, &$status, &$progress, &$queue) {
    $query = "SELECT * FROM `" . DOWNLOADS_TABLE . "` WHERE sessionID='$sessionID'";
    $result = mysql_query($query);
    
    if (mysql_affected_rows() < 1)
        return false;
    
    $fileID = mysql_result($result, 0, 'fileID');
    $status = mysql_result($result, 0, 'status');
    $progress = mysql_result($result, 0, 'progress');
    $queue = mysql_result($result, 0, 'queue');
    
    if ($queue == '')
        $queue = NULL;
    else
        $queue = explode(';', $queue);
    
    return true;
}

function removeSession($sessionID) {
    $query = "DELETE FROM `" . DOWNLOADS_TABLE . "` WHERE sessionID='$sessionID'";
    mysql_query($query);
}

?>


Wat WEL werkt:
de download starten met dl.php, naar phpMyAdmin gaan, en daar zie ik duidelijk dat de waarden zijn toegevoegd, en regelmatig geupdated worden. Dus phpMyAdmin heeft een bepaalde manier van werken die precies doet wat ik zou willen...

Wat ik al geprobeerd heb:
- In plaats van mysql_connect() de variant mysql_pconnect, met de hoop dat het mss via dezelfde verbinding wel zou lukken
- In dl.php na elke query de verbinding te sluiten (en dus telkens terug te openen wanneer dat nodig was). Dit was niet alleen trager, maar hielp ook niet...
- De parameter new_link op true gezet bij mysql_connect, om mysql te verplichten een 2de verbinding te maken... Hielp niet.

Dus wat ik jullie zou willen vragen: Hoe verhelp ik dit? Oh, en alle tips zijn welkom betreffend de code, om bijvoorbeeld dingen te versnellen :)

Dank bij voorbaat!

PS: zoals jullie wrsch al gemerkt hebben, deze code is niet volledig af (dl.php zou voor meerdere bestanden moeten werken, enz...)

Edit:
Opgelost, zie verder

[ Voor 26% gewijzigd door djbe op 17-08-2005 17:34 . Reden: Opgelost ]


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Je gebruikt mysql_pconnect. Probeer eens mysql_connect te gebruiken.

Edit: Och, dat had je al geprobeert :X

[ Voor 22% gewijzigd door Janoz op 17-08-2005 08:58 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 18-09 16:28

Bosmonster

*zucht*

Zomaar het eerste dat me opviel aan je code (helaas niks met mysql te maken):

Hoe kom je aan die $output_file variabele in je send_file functie?

Die zou in deze staat toch voor een foutmelding (of corrupte headers) moeten zorgen.

[ Voor 22% gewijzigd door Bosmonster op 17-08-2005 09:09 ]


Acties:
  • 0 Henk 'm!

Verwijderd

een goeie tip is om error notice in je php.ini op E_ALL te zetten.

error_reporting = E_ALL

Zo dus. Hierdoor zie je al meer dingen die fout kunnen gaan als je dit nog niet hebt.

Verder is er in php.ini een instelling mysql_max_.....Misschien als je die op -1 zet dat het dan wel werkt?

; Maximum number of persistent links. -1 means no limit.
mysql.max_persistent = -1

; Maximum number of links (persistent + non-persistent). -1 means no limit.
mysql.max_links = -1

Ik vraag me inmiddels wel af of dit hier iets mee te maken heeft. Maar maybe dat je er wat aan hebt.

[ Voor 10% gewijzigd door Verwijderd op 17-08-2005 09:53 ]


Acties:
  • 0 Henk 'm!

  • djbe
  • Registratie: Juni 2005
  • Laatst online: 13-06 03:43
Bedankt voor jullie snelle replies!
Dat van output_file had ik nog niet gemerkt |:( Die functie heb ik namelijk gedeeltelijk overgenomen van ergens :P Ik heb nu $output_file veranderd naar $name.
Wat jullie zeggen dat ik zou moeten veranderen in php.ini, dat zal moeilijk gaan denk ik, want het is niet mijn server... (lumumba voor diegenen die het kennen, LUC server) Ik heb geprobeerd een php.ini in mijn public_html te zetten met de volgende code:
code:
1
2
[ PHP]   <-- zonder een spatie maar moet wel anders denkt et forum dinges dat het php code is
error_reporting = E_ALL

maar toen ik phpinfo runde, kreeg ik geen andere waarde voor error_reporting. Mss handig voor jullie:
http://lumumba.uhasselt.be/~djbe/info.php
Ik kreeg ook geen extra errors (geen errors) bij het uitvoeren van getReport.php of dl.php.

Acties:
  • 0 Henk 'm!

  • Vesta
  • Registratie: November 2004
  • Niet online
je kunt de error_reporting ook in je script veranderen:
PHP:
1
error_reporting(E_ALL)


Terugkomend op je probleem:
Because session_start() does indeed prevent another page using session_start() from running until the first one is done, i use session_write_close() before doing any operation that takes significant time.
Probeer eens session_write_close() voor de send_file().

Acties:
  • 0 Henk 'm!

Verwijderd

de error reporting kan je ook veranderen door een .htaccess bestandje in je directory te zetten en hierin:

php_value error_reporting E_ALL

Te zetten.
Meer informatie hierover is hier te vinden.

Acties:
  • 0 Henk 'm!

  • djbe
  • Registratie: Juni 2005
  • Laatst online: 13-06 03:43
Whoa! Bedankt Vesta! Dat was het probleem! Nu werkt alles vlotjes :D
Dus eigenlijk, vanaf dat ik de sessionID erges opgeslagen heb, kan ik session_write_close() doen, bij elke script? (want momenteel gebruik ik het voor niets anders... Later mss wel).
Betreffend die .htaccess, ik heb er eentje in mn public_html dir gezet (zodat het overal geldig is, ens zien wat er allemaal fout is >:) ) met als enigste regel er in:
code:
1
php_value error_reporting E_ALL

en dan krijg ik (bij elk bestand dat ik probeer te openen) de volgende fout:
code:
1
2
3
4
5
6
7
8
Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator, webmaster+spamtrap@lumumba.uhasselt.be and inform them of the time the error occurred, and anything you might have done that may have caused the error.

More information about this error may be available in the server error log.
Apache Server at lumumba.uhasselt.be Port 80

Toch fel bedankt voor alle hulp!
Als jullie nog tips hebben, mogen jullie die altijd zeggen :D

edit:
Ja nu had ik een 2de vraag:
Als ik het bestand doorstuur zonder het mysql gedoe (in dl.php niet de progress updaten) dan haal ik veel hogere snelheden dan wanneer ik wel de progress update in de database. Hebben jullie enige tips hoe ik dit wat zou kunnen verbeteren?
(Met mySQL gedoe: 20KB/s, zonder: 240KB/s)

[ Voor 14% gewijzigd door djbe op 17-08-2005 17:32 . Reden: nog een vraagje ]


Acties:
  • 0 Henk 'm!

  • djbe
  • Registratie: Juni 2005
  • Laatst online: 13-06 03:43
Voor diegene die het nog geïnteresseerd zijn, ik heb de download snelheid kunnen verhogen door het volgende:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    // Transfer the file itself
    if ($file = fopen($path . $name, 'rb')) {
        $i = 0;
        $total = filesize($path . $name);
        
        // Calculate block size
        $blockSize = ($total / 100 > 1024 * 8) ? $total / 100 : 1024 * 8;
        
        while (!feof($file) and (connection_status() == 0)) {
            updateSession($sID, $fileID, 'transferring', (int) ((float) $i * 100 / $total), '');
            print(fread($file, $blockSize));
            flush();
            $i += $blockSize;
        }
        
        $status = (connection_status() == 0);
        fclose($file);
    }

Hiermee verhoogt de snelheid naarmate het bestand groter wordt 8)
Pagina: 1