Today I wanted to try out websockets because I heard that Google Chrome just integrated a preliminary version of it. I discovered that their isn’t a simple straightforward guide for doing this with apache2. Here is a simple guide to getting it working:
Starting with:
- Ubuntu 9.10 (I think it will work with most recent versions of ubuntu and other distributions will work if you change the package manager commands)
- Apache2 installed and working (punch
sudo apt-get install apache2into the terminal, type 127.0.0.1 into the browser to check) - Python 2.6.x installed and working
- Subversion
Step 1: Install mod_python and get it working with apache
- Punch
sudo apt-get install libapache2-mod-pythoninto the terminal - In /etc/apache2/sites-available/default change the part that looks like:
1 2 3 4
Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from allTo:
1 2 3 4 5 6 7
Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all AddHandler mod_python .py PythonHandler mod_python.publisher PythonDebug On
- Restart apache:
sudo /etc/init.d/apache2 restart - Test it by throwing something like this into a new file test.py in /var/www:
1 2
def index(req): return "Test successful"
- Navigate to localhost/test.py to see if the test is successful
Step 2: Get and Install pywebsocket
- Make sure you have subversion installed and run this in the terminal:
svn checkout http://pywebsocket.googlecode.com/svn/trunk/ pywebsocket-read-only - Now navigate into the pywebsocket-read-only folder where you downloaded it … aka
cd pywebsocket-read-only - Run
sudo python setup.py build - Then
sudo python setup.py install - Make a directory for the handlers … I made mine in my home directory as you can see below
- Now edit /etc/apache2/httpd.conf to include the following:
1 2 3 4 5
PythonPath "sys.path+['/usr/local/lib/python2.6/dist-packages/mod_pywebsocket']" PythonOption mod_pywebsocket.handler_root /home/travis/Desktop/websock_handlers PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
The first path /usr/local/lib/python2.6/dist-packages/mod_pywebsocket is where you installed mod_pywebsocket and should be in a similar location for you.
The second path /home/travis/Desktop/websock_handlers is where I put my handlers directory.
Remember to change the paths to fit your implementation
Step 3: Make some handlers where you said they would be above and you should be all set
The title’s a mouth full but the problem is very interesting and not too hard to break down.
- Runge Kutta is a numerical method technique very usefull for solving ordinary differential equations on computers
- It keeps computational errors to a minimum and keeps your simulations using ordinary differential equations stable.
- Basic explanation of the method I’m using can be found here: http://en.wikipedia.org/wiki/Runge-Kutta_methods
- HTML5 is the new html specification currently being implemented by browsers that allows many new things including:
- Use of canvas objects (2D drawing on the web, see below)
- Websockets (persistent connections between clients and servers)
- Video and Audio
What I’ve done is use a combination of the html canvas tools with the runge kutta technique implemented in javascript to show two masses/objects orbiting eachother. You can do a bunch of neat things with this including processing orbits etc. Check it out:
Javascript code:
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 64 65 66 67 68 69 70 71 72 73 74 75 | $(document).ready(function() { //get a reference to the canvas ctx = $('#canvas')[0].getContext("2d"); ax=100.0; ay=200.0; bx=200.0; by=100.0; adx=1; ady=1; bdx=-1; bdy=-1; time_step=1; setInterval(draw, 10); }); // runge kutta gravitational advance function f(p1,p2,dist){ var g=.05; return g*(1/dist^2)*((p2-p1)/dist); } function draw() { // stop iterating if they collide var dist=distance(ax,ay,bx,by); if(!dist<10){ k1_adx=f(ax,bx,dist); k2_adx=f(ax+time_step/2*k1_adx,bx,dist); k3_adx=f(ax+time_step/2*k2_adx,bx,dist); k4_adx=f(ax+time_step*k3_adx,bx,dist); adx+=time_step*(k1_adx+2*(k2_adx+k3_adx)+k4_adx)/6; k1_ady=f(ay,by,dist); k2_ady=f(ay+time_step/2*k1_ady,by,dist); k3_ady=f(ay+time_step/2*k2_ady,by,dist); k4_ady=f(ay+time_step*k3_ady,by,dist); ady+=time_step*(k1_ady+2*(k2_ady+k3_ady)+k4_ady)/6; k1_bdx=f(bx,ax,dist); k2_bdx=f(bx+time_step/2*k1_bdx,ax,dist); k3_bdx=f(bx+time_step/2*k2_bdx,ax,dist); k4_bdx=f(bx+time_step*k3_bdx,ax,dist); bdx+=time_step*(k1_bdx+2*(k2_bdx+k3_bdx)+k4_bdx)/6; k1_bdy=f(by,ay,dist); k2_bdy=f(by+time_step/2*k1_bdy,ay,dist); k3_bdy=f(by+time_step/2*k2_bdy,ay,dist); k4_bdy=f(by+time_step*k3_bdy,ay,dist); bdy+=time_step*(k1_bdy+2*(k2_bdy+k3_bdy)+k4_bdy)/6; } else{ console.log("stop moving\n"); } // update positions ax += adx; ay += ady; bx += bdx; by += bdy; ctx.clearRect(0,0,1000,800); ctx.beginPath(); ctx.arc(ax, ay, 10, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.arc(bx, by, 10, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); } function distance(x1,y1,x2,y2){ return Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2)); } |

