OpenLearning
  1. // by Sabrina Rispin
  2. // Activity Section: 5 & 6
  3. // Date: 13/4/15 - 24/4/15
  4. // Description: determines how many steps it takes for a point on the
  5. // complex plane c to escape the funciton z^2 + c upon iteration.
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <assert.h>
  10. #include <string.h>
  11. #include <netinet/in.h>
  12. #include <unistd.h>
  13. #include <math.h>
  14. #include "mandelbrot.h"
  15. #include "pixelColor.h"
  16.  
  17. // server defines
  18. #define SIMPLE_SERVER_VERSION 2.0
  19. #define REQUEST_BUFFER_SIZE 100
  20. #define DEFAULT_PORT 7191
  21. #define NUMBER_OF_PAGES_TO_SERVE 100
  22. // after serving this many pages the server will halt
  23.  
  24. // defines for escapeSteps, serveBMP and extract
  25. #define TRUE 1
  26. #define FALSE 0
  27. #define MAX_ITER 256
  28. #define SIZE 512 // ie the width of the image (also the height)
  29. #define POWER 2.0 // step = 2^-zoom
  30. #define ESCAPE_DISTANCE 4
  31. #define SIZE_OF_HEADER 54
  32. #define BYTES_PER_PIXEL 10
  33. #define SIZE_OF_BMP (SIZE * SIZE * BYTES_PER_PIXEL)
  34. #define MAX_LEN_INPUT 50
  35. #define OFFSET 2
  36. #define COLOR_MODE 'R'
  37.  
  38. // bits8 for serveBMP and triordinate for extract
  39. typedef unsigned char bits8;
  40. typedef struct _triordinate {
  41. double x;
  42. double y;
  43. int z;
  44. } triordinate;
  45.  
  46. static void serveHTML (int socket);
  47. static void serveBMP (int socket, double x, double y, int zoom);
  48. static triordinate extract (char *message);
  49. static int waitForConnection (int serverSocket);
  50. static int makeServerSocket (int portno);
  51.  
  52.  
  53. int main (int argc, char* argv[]) {
  54. // sets up the server
  55. printf ("************************************\n");
  56. printf ("Starting simple server %f\n", SIMPLE_SERVER_VERSION);
  57. printf ("Serving mandelbrots since 2012\n");
  58. printf ("Access server at http://localhost:%d/\n", DEFAULT_PORT);
  59. printf ("************************************\n");
  60. int serverSocket = makeServerSocket(DEFAULT_PORT);
  61. char request[REQUEST_BUFFER_SIZE];
  62. int numberServed = 0;
  63. while (numberServed < NUMBER_OF_PAGES_TO_SERVE) {
  64. printf ("*** So far served %d pages ***\n", numberServed);
  65. // STEP 1. wait for a request to be sent from a web browser,
  66. // then open a new connection for this conversation
  67. int connectionSocket = waitForConnection(serverSocket);
  68. // STEP 2. read the first line of the request
  69. int bytesRead = recv (connectionSocket, request, sizeof(request) - 1, 0);
  70. assert (bytesRead >= 0);
  71. // check that we were able to read some data from the connection
  72. // echo entire request to the console for debugging
  73. printf (" *** Received http request ***\n %s\n", request);
  74.  
  75. // Finds the start and end of the shorter, more useful request
  76. // from the url. Also checks there is an x, y and z.
  77. int startReq = 0;
  78. int endReq = 0;
  79. int valuesPresent = 0;
  80. while (request[endReq] != 'H') {
  81. if (request[endReq] == '/') {
  82. startReq = endReq;
  83. }
  84. if (request[endReq] == 'x' || request[endReq] == 'y' ||
  85. request[endReq] == 'z') {
  86. valuesPresent += 1;
  87. }
  88. endReq++;
  89. }
  90.  
  91. // Gotta terminate that new string!
  92. request[endReq] = '\0';
  93. char *shortRequest = &request[startReq];
  94.  
  95. printf("URL Short Request: %s\n", shortRequest);
  96. // STEP 3. send the browser stuff
  97. printf (" *** Sending http response ***\n");
  98.  
  99. // If x y and z serve BMP, else serve html interactive version
  100. if (valuesPresent == 3) {
  101. triordinate input = extract (shortRequest);
  102. serveBMP (connectionSocket, input.x, input.y, input.z);
  103. } else {
  104. printf ("HTML TIME\n");
  105. serveHTML (connectionSocket);
  106. }
  107. // STEP 4. close the connection after sending the page-
  108. // keep aust beautiful
  109. close (connectionSocket);
  110. ++numberServed;
  111. }
  112. // close the server connection after we are done-keep aust beautiful
  113. printf ("** shutting down the server **\n");
  114. close (serverSocket);
  115. return EXIT_SUCCESS;
  116. }
  117.  
  118. // mandelbrot functions
  119. int escapeSteps (double x, double y) {
  120. int escaped = FALSE;
  121. double zRe = 0.0;
  122. double zIm = 0.0;
  123.  
  124. // need the below in order to simultaneously update
  125. double newRe = 0.0;
  126. double newIm = 0.0;
  127.  
  128. //printf ("Real c: %lf, Imaginary c: %lf\n", x, y);
  129. // The calcs!
  130. int iter = 0;
  131. while ((iter < MAX_ITER) && (escaped != TRUE)) {
  132. iter++;
  133. newRe = zRe * zRe - zIm * zIm + x;
  134. newIm = 2 * zRe * zIm + y;
  135.  
  136. zRe = newRe;
  137. zIm = newIm;
  138.  
  139. if (zRe*zRe + zIm*zIm >= ESCAPE_DISTANCE) {
  140. escaped = TRUE;
  141. }
  142. }
  143.  
  144. //printf ("%d\n", iter);
  145. return iter;
  146. }
  147.  
  148. // server functions
  149. static void serveHTML (int socket) {
  150. char *message;
  151.  
  152. // first send the http response header
  153. message =
  154. "HTTP/1.0 200 Found\n"
  155. "Content-Type: text/html\n"
  156. "\n";
  157. printf ("about to send=> %s\n", message);
  158. write (socket, message, strlen (message));
  159.  
  160. // serves the html script for the interactive mandelbrot
  161. message =
  162. "<!DOCTYPE html>\n"
  163. "<script src=\"https://almondbread.cse.unsw.edu.au/tiles.js\"></script>"
  164. "\n";
  165. write (socket, message, strlen (message));
  166. }
  167.  
  168.  
  169. static void serveBMP (int socket, double x, double y, int zoom) {
  170. char *message;
  171.  
  172. // first send the http response header
  173. message = "HTTP/1.0 200 OK\r\n"
  174. "Content-Type: image/bmp\r\n"
  175. "\r\n";
  176. printf ("about to send=> %s\n", message);
  177. write (socket, message, strlen (message));
  178.  
  179. // serve the BMP header
  180. bits8 header[SIZE_OF_HEADER] = {
  181. 0x42, 0x4D, 0x36, 0x00, //
  182. 0x0C, 0x00, 0x00, 0x00,
  183. 0x00, 0x00, 0x36, 0x00,
  184. 0x00, 0x00, 0x28, 0x00,
  185. 0x00, 0x00, 0x00, 0x02,
  186. 0x00, 0x00, 0x00, 0x02,
  187. 0x00, 0x00, 0x01, 0x00,
  188. 0x18, 0x00, 0x00, 0x00,
  189. 0x00, 0x00, 0x00, 0x00,
  190. 0x0C, 0x00, 0x13, 0x0B,
  191. 0x00, 0x00, 0x13, 0x0B,
  192. 0x00, 0x00, 0x00, 0x00,
  193. 0x00, 0x00, 0x00, 0x00,
  194. 0x00, 0x00
  195. };
  196.  
  197. write (socket, header, sizeof (header));
  198.  
  199. // all the things and counters needed
  200. double step = pow (POWER, -zoom);
  201. double xStart = -step*SIZE/2 + step/2 + x;
  202. double xPos = xStart;
  203. double yPos = -step*SIZE/2 + step/2 + y;
  204. int xCount = 0;
  205. int yCount = 0;
  206. int arrayPos = 0;
  207. int iter;
  208.  
  209. // the bmp array!
  210. bits8 bmp[SIZE_OF_BMP];
  211.  
  212. while (yCount < SIZE) {
  213. while (xCount < SIZE) {
  214. // calcs number of iters to blow up then uses that to color
  215. iter = escapeSteps (xPos, yPos);
  216. bits8 blue;
  217. bits8 red;
  218. bits8 green;
  219. if (COLOR_MODE == 'B') {
  220. blue = stepsToRed (iter);
  221. red = stepsToGreen (iter);
  222. green = stepsToBlue (iter);
  223. } else if (COLOR_MODE == 'G') {
  224. green = stepsToRed (iter);
  225. blue = stepsToGreen (iter);
  226. red = stepsToBlue (iter);
  227. } else {
  228. red = stepsToRed (iter);
  229. green = stepsToGreen (iter);
  230. blue = stepsToBlue (iter);
  231. }
  232.  
  233. // add the pixel
  234. bmp[arrayPos] = blue;
  235. arrayPos++;
  236. bmp[arrayPos] = green;
  237. arrayPos++;
  238. bmp[arrayPos] = red;
  239. arrayPos++;
  240.  
  241. // to the next pixel! (Also keeps track of how many pixels)
  242. xPos += step;
  243. xCount++;
  244. }
  245.  
  246. // at the end of a row reset xPos, add a step to yPos and inc y
  247. xPos = xStart;
  248. yPos += step;
  249. yCount++;
  250. xCount = 0;
  251. }
  252.  
  253. write (socket, bmp, sizeof (bmp));
  254. }
  255.  
  256. // extracting x y z function
  257. triordinate extract (char *message) {
  258. // incase the values after x y and z are empty, set initial vals
  259. triordinate tri = {0, 0, 7};
  260.  
  261. // set start pos at extereme end
  262. // (not 0, if no update then start will include the whole string!)
  263. int xStart = strlen (message);
  264. int yStart = strlen (message);
  265. int zStart = strlen (message);
  266. int zEnd = strlen (message) - 1;
  267. // the final x, y and z as strings to go into ato_
  268. char x[MAX_LEN_INPUT];
  269. char y[MAX_LEN_INPUT];
  270. char z[MAX_LEN_INPUT];
  271.  
  272. // clears the array by filling it wil escaped 0
  273. memset (x, '\0', MAX_LEN_INPUT);
  274. memset (y, '\0', MAX_LEN_INPUT);
  275. memset (z, '\0', MAX_LEN_INPUT);
  276.  
  277. // this loops looks for an _ the looks as the next char
  278. // if x y or z set correspoding Start value
  279. // OFFSET = 2 because _x0.4 hence start of num is i (pos of _) + 2
  280. int i = 0;
  281. while (i < strlen (message)) {
  282. if (message[i] == '_') {
  283. if (message[i+1] == 'x') {
  284. xStart = i + OFFSET;
  285. } else if (message[i+1] == 'y') {
  286. yStart = i + OFFSET;
  287. } else if (message[i+1] == 'z') {
  288. zStart = i + OFFSET;
  289. }
  290. }
  291.  
  292. // _z5.bmp so . is the end of z
  293. if (message[i] == '.') {
  294. zEnd = i;
  295. }
  296. i++;
  297. }
  298.  
  299. // copies the specific string i.e. -0.4 (from _x-0.4) to x etc.
  300. // strncpy args: copyToString, copyFromString, length
  301. // note: yStart - xStart = length of _x-0.4 (-OFFSET for real len)
  302. strncpy (x, message + xStart, yStart - xStart - OFFSET);
  303. strncpy (y, message + yStart, zStart - yStart - OFFSET);
  304. strncpy (z, message + zStart, zEnd - zStart);
  305. //printf ("%s\n", x);
  306. //printf ("%s\n", y);
  307. //printf ("%s\n", z);
  308.  
  309. // eg if _x_y0.5_z6 there is no x val, strlen (x) == 0, don't update
  310. if (strlen (x) > 0) {
  311. tri.x = atof (x);
  312. }
  313. if (strlen (y) > 0) {
  314. tri.y = atof (y);
  315. }
  316. if (strlen (z) > 0) {
  317. tri.z = atol (z);
  318. }
  319.  
  320. return tri;
  321. }
  322.  
  323. // start the server listening on the specified port number
  324. static int makeServerSocket (int portNumber) {
  325. // create socket
  326. int serverSocket = socket (AF_INET, SOCK_STREAM, 0);
  327. assert (serverSocket >= 0);
  328. // check there was no error in opening the socket
  329. // bind the socket to the listening port (7191 in this case)
  330. struct sockaddr_in serverAddress;
  331. serverAddress.sin_family = AF_INET;
  332. serverAddress.sin_addr.s_addr = INADDR_ANY;
  333. serverAddress.sin_port = htons (portNumber);
  334. // tell the server to restart immediately after a previous shutdown
  335. // even if it looks like the socket is still in use
  336. // otherwise we might have to wait a little while before rerunning the
  337. // server once it has stopped
  338. const int optionValue = 1;
  339. setsockopt (serverSocket, SOL_SOCKET, SO_REUSEADDR, &optionValue, sizeof (int));
  340. int bindSuccess = bind (serverSocket, (struct sockaddr*)&serverAddress, sizeof (serverAddress));
  341. assert (bindSuccess >= 0);
  342. // if this assert fails wait a short while to let the operating
  343. // system clear the port before trying again
  344. return serverSocket;
  345. }
  346.  
  347. // wait for a browser to request a connection,
  348. // returns the socket on which the conversation will take place
  349. static int waitForConnection (int serverSocket) {
  350. // listen for a connection
  351. const int serverMaxBacklog = 10;
  352. listen (serverSocket, serverMaxBacklog);
  353. // accept the connection
  354. struct sockaddr_in clientAddress;
  355. socklen_t clientLen = sizeof (clientAddress);
  356. int connectionSocket = accept (serverSocket, (struct sockaddr*)&clientAddress, &clientLen);
  357. assert (connectionSocket >= 0);
  358. // check for connection error
  359. return connectionSocket;
  360. }

Download file: mandelbrot.c (11.4 KB)

Comments

Loading
Error: Loading CSS chunk vendors-node_modules_fortawesome_pro-regular-svg-icons_faGlobe_js-node_modules_fortawesome_pr-d462f3 failed. (error: https://assets.openlearning.com/chunks_live/vendors-node_modules_fortawesome_pro-regular-svg-icons_faGlobe_js-node_modules_fortawesome_pr-d462f3.8fd07ef9993d3220.css)

Chat