- // by Sabrina Rispin
- // Activity Section: 5 & 6
- // Date: 13/4/15 - 24/4/15
- // Description: determines how many steps it takes for a point on the
- // complex plane c to escape the funciton z^2 + c upon iteration.
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <string.h>
- #include <netinet/in.h>
- #include <unistd.h>
- #include <math.h>
- #include "mandelbrot.h"
- #include "pixelColor.h"
- // server defines
- #define SIMPLE_SERVER_VERSION 2.0
- #define REQUEST_BUFFER_SIZE 100
- #define DEFAULT_PORT 7191
- #define NUMBER_OF_PAGES_TO_SERVE 100
- // after serving this many pages the server will halt
- // defines for escapeSteps, serveBMP and extract
- #define TRUE 1
- #define FALSE 0
- #define MAX_ITER 256
- #define SIZE 512 // ie the width of the image (also the height)
- #define POWER 2.0 // step = 2^-zoom
- #define ESCAPE_DISTANCE 4
- #define SIZE_OF_HEADER 54
- #define BYTES_PER_PIXEL 10
- #define SIZE_OF_BMP (SIZE * SIZE * BYTES_PER_PIXEL)
- #define MAX_LEN_INPUT 50
- #define OFFSET 2
- #define COLOR_MODE 'R'
- // bits8 for serveBMP and triordinate for extract
- typedef unsigned char bits8;
- typedef struct _triordinate {
- double x;
- double y;
- int z;
- } triordinate;
- static void serveHTML (int socket);
- static void serveBMP (int socket, double x, double y, int zoom);
- static triordinate extract (char *message);
- static int waitForConnection (int serverSocket);
- static int makeServerSocket (int portno);
- int main (int argc, char* argv[]) {
- // sets up the server
- printf ("************************************\n");
- printf ("Starting simple server %f\n", SIMPLE_SERVER_VERSION);
- printf ("Serving mandelbrots since 2012\n");
- printf ("Access server at http://localhost:%d/\n", DEFAULT_PORT);
- printf ("************************************\n");
- int serverSocket = makeServerSocket(DEFAULT_PORT);
- char request[REQUEST_BUFFER_SIZE];
- int numberServed = 0;
- while (numberServed < NUMBER_OF_PAGES_TO_SERVE) {
- 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 = recv (connectionSocket, request, sizeof(request) - 1, 0);
- 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);
- // Finds the start and end of the shorter, more useful request
- // from the url. Also checks there is an x, y and z.
- int startReq = 0;
- int endReq = 0;
- int valuesPresent = 0;
- while (request[endReq] != 'H') {
- if (request[endReq] == '/') {
- startReq = endReq;
- }
- if (request[endReq] == 'x' || request[endReq] == 'y' ||
- request[endReq] == 'z') {
- valuesPresent += 1;
- }
- endReq++;
- }
- // Gotta terminate that new string!
- request[endReq] = '\0';
- char *shortRequest = &request[startReq];
- printf("URL Short Request: %s\n", shortRequest);
- // STEP 3. send the browser stuff
- printf (" *** Sending http response ***\n");
- // If x y and z serve BMP, else serve html interactive version
- if (valuesPresent == 3) {
- triordinate input = extract (shortRequest);
- serveBMP (connectionSocket, input.x, input.y, input.z);
- } else {
- printf ("HTML TIME\n");
- serveHTML (connectionSocket);
- }
- // 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;
- }
- // mandelbrot functions
- int escapeSteps (double x, double y) {
- int escaped = FALSE;
- double zRe = 0.0;
- double zIm = 0.0;
- // need the below in order to simultaneously update
- double newRe = 0.0;
- double newIm = 0.0;
- //printf ("Real c: %lf, Imaginary c: %lf\n", x, y);
- // The calcs!
- int iter = 0;
- while ((iter < MAX_ITER) && (escaped != TRUE)) {
- iter++;
- newRe = zRe * zRe - zIm * zIm + x;
- newIm = 2 * zRe * zIm + y;
- zRe = newRe;
- zIm = newIm;
- if (zRe*zRe + zIm*zIm >= ESCAPE_DISTANCE) {
- escaped = TRUE;
- }
- }
- //printf ("%d\n", iter);
- return iter;
- }
- // server functions
- static void serveHTML (int socket) {
- char *message;
- // first send the http response header
- message =
- "HTTP/1.0 200 Found\n"
- "Content-Type: text/html\n"
- "\n";
- printf ("about to send=> %s\n", message);
- write (socket, message, strlen (message));
- // serves the html script for the interactive mandelbrot
- message =
- "<!DOCTYPE html>\n"
- "<script src=\"https://almondbread.cse.unsw.edu.au/tiles.js\"></script>"
- "\n";
- write (socket, message, strlen (message));
- }
- static void serveBMP (int socket, double x, double y, int zoom) {
- char *message;
- // first send the http response header
- 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));
- // serve the BMP header
- bits8 header[SIZE_OF_HEADER] = {
- 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, header, sizeof (header));
- // all the things and counters needed
- double step = pow (POWER, -zoom);
- double xStart = -step*SIZE/2 + step/2 + x;
- double xPos = xStart;
- double yPos = -step*SIZE/2 + step/2 + y;
- int xCount = 0;
- int yCount = 0;
- int arrayPos = 0;
- int iter;
- // the bmp array!
- bits8 bmp[SIZE_OF_BMP];
- while (yCount < SIZE) {
- while (xCount < SIZE) {
- // calcs number of iters to blow up then uses that to color
- iter = escapeSteps (xPos, yPos);
- bits8 blue;
- bits8 red;
- bits8 green;
- if (COLOR_MODE == 'B') {
- blue = stepsToRed (iter);
- red = stepsToGreen (iter);
- green = stepsToBlue (iter);
- } else if (COLOR_MODE == 'G') {
- green = stepsToRed (iter);
- blue = stepsToGreen (iter);
- red = stepsToBlue (iter);
- } else {
- red = stepsToRed (iter);
- green = stepsToGreen (iter);
- blue = stepsToBlue (iter);
- }
- // add the pixel
- bmp[arrayPos] = blue;
- arrayPos++;
- bmp[arrayPos] = green;
- arrayPos++;
- bmp[arrayPos] = red;
- arrayPos++;
- // to the next pixel! (Also keeps track of how many pixels)
- xPos += step;
- xCount++;
- }
- // at the end of a row reset xPos, add a step to yPos and inc y
- xPos = xStart;
- yPos += step;
- yCount++;
- xCount = 0;
- }
- write (socket, bmp, sizeof (bmp));
- }
- // extracting x y z function
- triordinate extract (char *message) {
- // incase the values after x y and z are empty, set initial vals
- triordinate tri = {0, 0, 7};
- // set start pos at extereme end
- // (not 0, if no update then start will include the whole string!)
- int xStart = strlen (message);
- int yStart = strlen (message);
- int zStart = strlen (message);
- int zEnd = strlen (message) - 1;
- // the final x, y and z as strings to go into ato_
- char x[MAX_LEN_INPUT];
- char y[MAX_LEN_INPUT];
- char z[MAX_LEN_INPUT];
- // clears the array by filling it wil escaped 0
- memset (x, '\0', MAX_LEN_INPUT);
- memset (y, '\0', MAX_LEN_INPUT);
- memset (z, '\0', MAX_LEN_INPUT);
- // this loops looks for an _ the looks as the next char
- // if x y or z set correspoding Start value
- // OFFSET = 2 because _x0.4 hence start of num is i (pos of _) + 2
- int i = 0;
- while (i < strlen (message)) {
- if (message[i] == '_') {
- if (message[i+1] == 'x') {
- xStart = i + OFFSET;
- } else if (message[i+1] == 'y') {
- yStart = i + OFFSET;
- } else if (message[i+1] == 'z') {
- zStart = i + OFFSET;
- }
- }
- // _z5.bmp so . is the end of z
- if (message[i] == '.') {
- zEnd = i;
- }
- i++;
- }
- // copies the specific string i.e. -0.4 (from _x-0.4) to x etc.
- // strncpy args: copyToString, copyFromString, length
- // note: yStart - xStart = length of _x-0.4 (-OFFSET for real len)
- strncpy (x, message + xStart, yStart - xStart - OFFSET);
- strncpy (y, message + yStart, zStart - yStart - OFFSET);
- strncpy (z, message + zStart, zEnd - zStart);
- //printf ("%s\n", x);
- //printf ("%s\n", y);
- //printf ("%s\n", z);
- // eg if _x_y0.5_z6 there is no x val, strlen (x) == 0, don't update
- if (strlen (x) > 0) {
- tri.x = atof (x);
- }
- if (strlen (y) > 0) {
- tri.y = atof (y);
- }
- if (strlen (z) > 0) {
- tri.z = atol (z);
- }
- return tri;
- }
- // start the server listening on the specified port number
- static int makeServerSocket (int portNumber) {
- // create socket
- int serverSocket = socket (AF_INET, SOCK_STREAM, 0);
- assert (serverSocket >= 0);
- // check there was no error in opening the socket
- // 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
- const int optionValue = 1;
- 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
- static 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);
- assert (connectionSocket >= 0);
- // check for connection error
- return connectionSocket;
- }
Download file:
mandelbrot.c
(11.4 KB)
