FREE THOUGHT · FREE SOFTWARE · FREE WORLD

Home  »  PHP  »  Faster Form Submission and Processing with fsockopen

by 6 comments

[hide]

Speedy Forms using background-requestsThis is part II of Faster POST and GET Form Submissions, illustrating a few simple methods of speeding up POST and GET form submissions and form processing by utilizing background requests with fsockopen.

Background Requests with PHP

Instead of sending the form results to thanks.php and having thanks.php both process the form and display the post-processing response (like a thank you message), instead have thanks.php forward the form results to background.php while simultaneously displaying the thank you message.

Background Request example with fsockopen

So the form is on the page survey.php, and the action of the form is set to thanks.php, and the background request is made to background.php

survey.php - the survey form

This displays the survey form and sends the results via an HTTP POST to /thanks.php

<form action="/thanks.php" method="post">
  <label for="text1">Enter Survey Answers</label>
  <input type="text" name="text1" id="text1" value="" />
  <input type="submit" value="Submit Survey Answers" />
</form>

thanks.php - the response / forwarder

This file receives the text1 value and displays a thank you message, at the same time it fires off an HTTP GET request to /background.php with text1 added as a GET variable.

Note: I am using HTTP/1.0 protocol which is faster than HTTP/1.1 for various reasons you can read about elsewhere on AskApache.

<?php $text1=$_POST['text1']; ?>
 
<h2>Thanks <?php echo $text1; ?>!</h2>
 
<?php
$fp = fsockopen("www.askapache.com", 80, $errno, $errstr, 30);
if (!$fp) echo "$errstr ($errno)\n";
else {
  fwrite($fp, "GET /background.php?text1=$text1 HTTP/1.0\r\nHost: www.askapache.com\r\n\r\n");
  fclose($fp);
}
?>

background.php - server-side form processing

This file is requested by the server, and run on the server, receiving/sending nothing to the client, which is just fantastic. Where the // processing on text1 is located is where you can run code that would normally slow down your client.

  • Sending an email with the results using phpmailer, sendmail, swiftmailer, etc.
  • Add or modify a mysql database record using the $text1 value
  • Run any other server-side script, maybe anti-virus or anti-spam
<?php
$text1=$_GET['text1'];
// processing on text1
?>

Stay tuned for part III, where I will show some advanced methods like setting up a fsockopen-based POST variable forwarder, POST to SESSION conversion, implementing gzip compression and base64 encoding to obfuscate/speed up variable passing in HTTP requests, and using cURL / libcurl instead of fsockopen. I might also touch on pfsockopen for persistant socket-based connections. Probably will be published at the end of March, I'm going on vacation!

Use GET for AJAX Requests

The Yahoo! Mail team found that when using XMLHttpRequest, POST is implemented in the browsers as a two-step process: sending the headers first, then sending data. So it's best to use GET, which only takes one TCP packet to send (unless you have a lot of cookies). The maximum URL length in IE is 2K, so if you send more than 2K data you might not be able to use GET.

An interesting side affect is that POST without actually posting any data behaves like GET. Based on the HTTP specs, GET is meant for retrieving information, so it makes sense (semantically) to use GET when you're only requesting data, as opposed to sending data to be stored server-side.

Post-load Components

You can take a closer look at your page and ask yourself: "What's absolutely required in order to render the page initially?". The rest of the content and components can wait.

It's good when the performance goals are inline with other web development best practices. In this case, the idea of progressive enhancement tells us that JavaScript, when supported, can improve the user experience but you have to make sure the page works even without JavaScript. So after you've made sure the page works fine, you can enhance it with some post-loaded scripts that give you more bells and whistles such as drag and drop and animations.

March 4th, 2008

Comments Welcome

  • http://pixeline.be/ Alexandre Plennevaux

    Hi!

    Thank a lot for this interesting article. Question: how do you do error management in this technique? Specifically, what happens if some sort of error happens in the processing of background.php? You've just displayed a "Thank you" message, and then afterwards, you cannot inform the user that an error occurred.
    Or, can you?

  • http://www.askapache.com/ AskApache

    @ Alexandre

    Excellent question, and one which I have been experimenting and learning about as recently as last month.. I am saving this ultra-cool technique for part IIII, just because it is so radically bad@ss.

    the right direction

    function close_abort(){
      global $fp;
      @ fclose($fp);
    }
     
    register_shutdown_function(close_abort); // run function on connection close/reset
    ignore_user_abort(true); // run script in background
    set_time_limit(0); // run script forever
     
    // open errorlog.txt in append mode
    $fp = @ fopen('errorlog.txt', 'a+');
     
    do{
      sleep(15);  // pauses script execution for 15 seconds
      echo "n."; // to keep connection alive by sending data
     
      ob_start(); // start a buffer to capture output
      phpinfo();  // print php info to output
      $emess=ob_get_clean(); // save output into emess var
     
      fwrite($fp, $emess);   // write emess value to errorlog.txt
      break;  // outie
    } while(true);
     
    @ fclose($fp); // close errorlog.txt filepointer
     
    // display emess for debugging
    //header('Content-type: text/plain');
    //echo $emess;
  • http://www.pgprojects.com/ Pawel

    Hello, do you happen to know when part III will be published? I cant wait ;)

    Thanks!

  • http://www.pianosventure.com bayson

    Wat about using cURL instead of fsockopen?

  • Chris C

    Nope...

    $fp = fsockopen("www.askapache.com", 80, $errno, $errstr, 30);

    That 30 means 30sec. This is NOT async! In particular if the server on the other side is down this piece of code will hang for 30 seconds. Also the fwrite is going to take its sweet time to execute if there are problems on the network (that you can limit with stream_set_timeout($fp, $my_timeout). The best you can do is to set a low timeout on fsockopen to 0.1 (100ms) and $my_timeout to 100ms. You risk though, that the request will timeout.

    Regarding @Alexandre solution:

    You forgot to send a Connection: close (See http://stackoverflow.com/questions/124462/asynchronous-php-calls Christian Davén's answer). But if you use a MVC framework, it may not be practical.

    I would also very careful to use set_time_limit(0);

    This code also seems useless:

    do{
      ...
      break;  // outie
    } while(true);
  • http://www.askapache.com/ AskApache

    @Chris C

    Nice feedback.. what I actually do instead of hardcoding the hostname is to use $_SERVER['SERVER_ADDR'] to connect, since this is all meant to be done on the same site. The background processing is by another php process on the same server, though you could easily use multiple servers. You would also probably enjoy reading my post about a custom fsockopen class I wrote using snoopy, libcurl, etc..

    Here is what I actually use when the server has access to many IP devices in order to make the connection come from the correct IP. I use the stream_socket_client to open the socket instead of fsockopen.

    $opts=array('socket'=> array('bindto'=>"{$_SERVER['SERVER_ADDR']}:0"));
    $h = stream_context_create($opts);
    $fp = @stream_socket_client("{$host}:{$port}", $errno, $errstr, $tval, STREAM_CLIENT_CONNECT, $h);

My Online Tools
My Picks
Twitter

  • : Ratpoison, a lean mean WM for Linux (urvxt), I love it
  • : You understand, what I need to know is exactly what happens to the passengers in an elevator when it falls into emptiness - Einstein
  • : It's not process, its content. That's what makes good products. -jobs
  • : Just bought some great BOSE headphones from best buy


Related Articles
Newest Posts

WordPress Development
Hacking and Hackers

The use of "hacker" to mean "security breaker" is a confusion on the part of the mass media. We hackers refuse to recognize that meaning, and continue using the word to mean someone who loves to program, someone who enjoys playful cleverness, or the combination of the two. See my article, On Hacking.
-- Richard M. Stallman






It's very simple - you read the protocol and write the code. -Bill Joy

Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 License, just credit with a link.
This site is not supported or endorsed by The Apache Software Foundation (ASF). All software and documentation produced by The ASF is licensed. "Apache" is a trademark of The ASF. NCSA HTTPd.
UNIX ® is a registered Trademark of The Open Group. POSIX ® is a registered Trademark of The IEEE.

| Google+

Site Map | Contact Webmaster | License and Disclaimer | Terms of Service

↑ TOPMain