// Name: John Luo, Sean Batongbacal
// Date: 2014 / 04 / 19
// Descr: A local server that serves inmaes of the Mandelbrot set
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include "mandelbrot.h"
#include "pixelColor.h"
int waitForConnection (int serverSocket);
int makeServerSocket (int portno);
void serveHTML (int socket,int viewer,double x,double y,int z);
static double exponential2(int exponent);
#define SIMPLE_SERVER_VERSION 2.0
#define REQUEST_BUFFER_SIZE 1000
#define DEFAULT_PORT 7191
#define MAX_STEPS 256
#define SIZE 512 // sides in px
#define LEFT -2.0
#define RIGHT 2.0
#define TOP 2.0
#define BOTTOM -2.0
#define TRUE 1
#define FALSE 0
int main (int argc, char* argv[]) {
printf ("************************************\n");
printf ("Starting simple server %f\n", SIMPLE_SERVER_VERSION);
printf ("Serving mandelbrot sets since 2014\n");
printf ("Access this server at http://localhost:%d/\n", DEFAULT_PORT);
printf ("************************************\n");
int serverSocket = makeServerSocket(DEFAULT_PORT);
char request[REQUEST_BUFFER_SIZE];
int numberServed = 0;
while (TRUE) {
printf ("*** So far served %d pages ***\n", numberServed);
// STEP 1. wait for a request to be sent from a web browser,
// then open a new connection for this conversation
int connectionSocket = waitForConnection(serverSocket);
// STEP 2. read the first line of the request
int bytesRead;
bytesRead = read (connectionSocket, request, (sizeof(request)-1));
assert (bytesRead >= 0);
// check that we were able to read some data from the connection
// echo entire request to the console for debugging
printf (" *** Received http request ***\n %s\n", request);
double x = 0;
double y = 0;
int z = 7;
char requestedFile[sizeof(request)];
int viewer;
// STEP 3. send the browser a simple html page using http
printf (" *** Sending http response ***\n");
sscanf (request," GET %s HTTP/1.1",requestedFile);
printf ("\n **** THE REQUESTED FILE IS %s ***** \n",requestedFile);
if(strlen(requestedFile)==1){
viewer = TRUE;
} else{
sscanf (request," GET /tile_x%lf_y%lf_z%d.bmp",&x,&y,&z);
viewer = FALSE;
}
serveHTML(connectionSocket,viewer,x,y,z);
// STEP 4. close the connection after sending the page- keep aust beautiful
close (connectionSocket);
numberServed++;
}
// close the server connection after we are done- keep aust beautiful
printf ("** shutting down the server **\n");
close (serverSocket);
return EXIT_SUCCESS;
}
void serveHTML(int socket,int viewer,double x,double y,int z) {
char* message; // used to be const? --Sean
// first send the http response header
// (if you write stings one after another like this on separate
// lines the c compiler kindly joins them togther for you into
// one long string)
if(viewer == FALSE){
message = "HTTP/1.0 200 OK\r\n"
"Content-Type: image/bmp\r\n"
"\r\n";
printf ("about to send=> %s\n", message);
write (socket, message, strlen (message));
// now send the BMP header
unsigned char bmpHeader[] = {
0x42,0x4d,0x36,0x00,0x0c,0x00,0x00,0x00,
0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,
0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x0c,0x00,0x13,0x0b,
0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00
};
write (socket, bmpHeader, sizeof(bmpHeader));
// iterates calculation and sending
int col = 0;
int row = SIZE;
double currentx;
double currenty;
int steps;
double zoom = exponential2(-z+7);
unsigned char pixelArray[3] = {};
while(row>0){
while(col<SIZE){
currentx = (LEFT + col*(RIGHT-LEFT)/SIZE) * zoom + x;
currenty = (TOP + row*(BOTTOM-TOP)/SIZE) * zoom + y;
steps = escapeSteps(currentx,currenty);
pixelArray[0] = stepsToBlue(steps);
pixelArray[1] = stepsToGreen(steps);
pixelArray[2] = stepsToRed(steps);
col++;
write(socket,pixelArray, sizeof(pixelArray));
}
col = 0;
row--;
}
} else{
message = "HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"\r\n";
char* viewerMessage = "<!DOCTYPE html>"
"<script src='http://almondbread.cse.unsw.edu.au/tiles.js'></script>";
write(socket,message,strlen(message));
write(socket,viewerMessage,strlen(viewerMessage));
}
}
// start the server listening on the specified port number
int makeServerSocket (int portNumber) {
// create socket
int serverSocket = socket (AF_INET, SOCK_STREAM, 0);
// check there was no error in opening the socket
assert (serverSocket >= 0);
// bind the socket to the listening port (7191 in this case)
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = INADDR_ANY;
serverAddress.sin_port = htons (portNumber);
// tell the server to restart immediately after a previous shutdown
// even if it looks like the socket is still in use
// otherwise we might have to wait a little while before rerunning the
// server once it has stopped
int optionValue = 1; // used to be const? --Sean
setsockopt (
serverSocket,
SOL_SOCKET,
SO_REUSEADDR,
&optionValue,
sizeof (int)
);
int bindSuccess =
bind (
serverSocket,
(struct sockaddr*) &serverAddress,
sizeof (serverAddress)
);
assert (bindSuccess >= 0);
// if this assert fails wait a short while to let the operating
// system clear the port before trying again
return serverSocket;
}
// wait for a browser to request a connection,
// returns the socket on which the conversation will take place
int waitForConnection (int serverSocket) {
// listen for a connection
const int serverMaxBacklog = 10;
listen (serverSocket, serverMaxBacklog);
// accept the connection
struct sockaddr_in clientAddress;
socklen_t clientLen = sizeof (clientAddress);
int connectionSocket =
accept (
serverSocket,
(struct sockaddr*) &clientAddress,
&clientLen
);
// check for connection error
assert (connectionSocket >= 0);
return connectionSocket;
}
// our stuff
int escapeSteps (double x, double y) {
// x = scaled x coordinate of pixel (to lie in Mandelbrot X scale (-2.5,1))
// y = scaled y coordinate of pixel (to lie in Mandelbrot Y scale (-1,1))
double x0 = 0.0;
double y0 = 0.0;
int iteration = 0;
double xtemp;
while ((x0*x0 + y0*y0 < 2*2) && (iteration < MAX_STEPS)) {
xtemp = x0*x0 - y0*y0 + x;
y0 = 2*x0*y0 + y;
x0 = xtemp;
iteration++;
}
// debug code
// printf ("x is %f, y is %f, %d\n", x0, y0, iteration);
// old print statement
// if (x0 * x0 + y0 * y0 <= 4) {
// printf ("*");
// } else {
// printf (" ");
// }
return iteration;
}
/*
// below should be identical to whats in pixelColor.c?
unsigned char stepsToRed (int steps) {
unsigned char intensity;
// here is where we transform steps into intensity
intensity = steps;
// we could change this later
return intensity;
}
unsigned char stepsToBlue (int steps) {
unsigned char intensity;
// here is where we transform steps into intensity
intensity = steps;
// we could change this later
return intensity;
}
unsigned char stepsToGreen (int steps) {
unsigned char intensity;
// here is where we transform steps into intensity
intensity = steps;
// we could change this later
return intensity;
}
*/
// any other functions must be static
// exp2 -> returns the result of 2^x
static double exponential2(int exponent){
double z = 1;
if(exponent > 0){
while(exponent > 0){
z = z * 2;
exponent--;
}
} else if(exponent < 0){
while(exponent < 0){
z = z / 2;
exponent++;
}
}
return z;
}
Download file:
mandelbrot.c
(8.6 KB)