/* File name : server.c Related file: client.c Author : Ting-jen Yen (yentj@cs.nyu.edu) Date : 1998 (for Yap's Visualization Class) Description : This is a simple iterative server that listens at port 1234. It will accept a number (unsigned, integer or float) from the client, and returns twice the number to the client. You can can access this server by running the client program (see file client.c), or just using "telnet" to connect to the server. Usage: Simply type "server" in the host machine to serve at default port 1234. Otherwise type "server -p ". How to compile : On Solaris 2 : % gcc -o server server.c -lsocket On SGI machies : % gcc -o server server.c */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "state.h" int server_sock, con_sock; int srv_port = 1234; struct sockaddr_in source; const int buffMax=1000; const int MAX_POINTS = 2000000; const int commandMax =1024; const int numState = 53; const char* stateName[numState] = { /*"AK",*/ "AL", "AR", "AZ", "CA", "CO", "CT", "DC", "DE", "FL", "GA", "GU", "HI", "IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", "MD", "ME", "MI", "MN", "MO", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", "NM", "NV", "NY", "OH", "OK", "OR", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VI", "VT", "WA", "WI", "WV", "WY" }; //const int screenWidth=640; //const int screenHeight=480; Line* resultTLine; // the result of query char TLineBuff[buffMax]; int total_tline_num = 0; int numBlock=0; //test the transmition between server and client. the number of blocks State state[numState]; const char* map_dir = "data"; // the subdirectory that saves the map data const char* file_suffix = "Lines.txt"; // the suffix of map data file char file_name[128]; // map file name double left_bound,right_bound,bottom_bound,top_bound; // the boundary of the whole USA map void getTLine(double x_left, double x_right, double y_top, double y_bottom) { int stateIndex[numState]; int file_num = 0; total_tline_num = 0; for ( int j = 0; j < numState; j++) { double state_left = state[j].getLeftBound(); double state_right = state[j].getRightBound(); double state_top = state[j].getTopBound(); double state_bottom = state[j].getBottomBound(); //printf("state_left=%d\n", state_left); //printf("state_right=%d\n", state_right); //printf("state_bottom=%d\n", state_bottom); //printf("state_top=%d\n", state_top); int count=0; if (x_left>=state_left && x_left<=state_right && y_bottom<=state_bottom && y_top>=state_bottom) { count++; } if (x_left>=state_left && x_left<=state_right && y_bottom<=state_top && y_top>=state_top) { count++; } if (x_left>=state_left && x_left<=state_right && y_top>=state_top && y_bottom<=state_bottom) { count++; } if (x_right>=state_left && x_right<=state_right && y_bottom>=state_bottom && y_top<=state_top) { count++; } if (x_right>=state_left && x_right<=state_right && y_bottom<=state_bottom && y_top>=state_bottom) { count++; } if (x_right>=state_left && x_right<=state_right && y_bottom<=state_top && y_top>=state_top) { count++; } if (x_right>=state_left && x_right<=state_right && y_top>=state_top && y_bottom<=state_bottom) { count++; } if (x_right>=state_left && x_right<=state_right && y_top<=state_top && y_bottom>=state_bottom) { count++; } if (x_left<=state_left && x_right>=state_right && y_bottom<=state_bottom && y_top>=state_bottom) { count++; } if (x_left<=state_left && x_right>=state_right && y_bottom<=state_top && y_top>=state_top) { count++; } if (x_left<=state_left && x_right>=state_right && y_bottom>=state_bottom && y_top<=state_top) { count++; } if (x_left<=state_left && x_right>=state_right && y_bottom<=state_bottom && y_top>=state_top) { count++; } if (x_left>=state_left && x_right<=state_right && y_bottom<=state_bottom && y_top>=state_bottom) { count++; } if (x_left>=state_left && x_right<=state_right && y_bottom<=state_top && y_top>=state_top) { count++; } if (x_left>=state_left && x_right<=state_right && y_bottom>=state_bottom && y_top<=state_top) { count++; } if (x_left>=state_left && x_right<=state_right && y_bottom<=state_bottom && y_top>=state_top) { count++; } if (count>=1) { //printf("FileNum=%d\n",file_num); stateIndex[file_num] = j; file_num++; } } // end for state // determine if the lines are in the boundary printf("total state file_num=%d\n", file_num); for (int i = 0; i < file_num; i++ ) { // i is for state index int k = stateIndex[i]; for (int j = 0; j < state[k].get_total_lines(); j++){ // j is for line index int count = 0; double point_top; double point_bottom; double point_left; double point_right; if ( state[k].lines[j].startx < state[k].lines[j].endx ){ point_left = state[k].lines[j].startx; point_right = state[k].lines[j].endx; } else { point_left = state[k].lines[j].endx; point_right = state[k].lines[j].startx; } if ( state[k].lines[j].starty < state[k].lines[j].endy ){ point_top = state[k].lines[j].endy; point_bottom = state[k].lines[j].starty; } else { point_top = state[k].lines[j].starty; point_bottom = state[k].lines[j].endy; } if (point_top>=y_top && point_bottom<=y_top) { if (point_right<=x_right && point_left>=point_left) { count++; } else if (point_left<=x_left && point_right>=x_left) { count++; } else if (point_right>=x_right && point_left<=x_right) { count++; } else if (point_right>=x_left && point_left<=x_left) { count++; } } else if (point_top<=y_top && point_bottom>=y_bottom) { if (point_left<=x_left && point_right>=x_left) { count++; } else if (point_right>=x_right && point_left<=x_right) { count++; } else if (point_right<=x_right && point_left>=x_left) { count++; } else if (point_right>=x_right && point_left<=x_left) { count++; } } else if (point_top>=y_bottom && point_bottom<=y_bottom) { if (point_right<=x_right && point_left>=point_left) { count++; } else if (point_left<=x_left && point_right>=x_left) { count++; } else if (point_right>=x_right && point_left<=x_right) { count++; } else if (point_right>=x_left && point_left<=x_left) { count++; } } //printf("count=%d\n", count); if (count>=1) { resultTLine[total_tline_num].startx = state[k].lines[j].startx; resultTLine[total_tline_num].endx = state[k].lines[j].endx; resultTLine[total_tline_num].starty = state[k].lines[j].starty; resultTLine[total_tline_num].endy = state[k].lines[j].endy; total_tline_num++; } // if } // end for j } // end for i } // end of getTLine() /***************************************************************/ /* Compute boundary of the whole USA map */ /***************************************************************/ void getUSBoundary(){ FILE* f; for ( int i = 0; i < numState; i++){ state[i].setName(stateName[i]); strcpy(file_name, map_dir); strcat(file_name, "/"); strcat(file_name, state[i].getName()); strcat(file_name, file_suffix); f = fopen(file_name, "r"); int extend_left, extend_right, extend_bottom, extend_top; fscanf(f, "%i", &extend_left); fscanf(f, "%i", &extend_right); fscanf(f, "%i", &extend_bottom); fscanf(f, "%i", &extend_top); state[i].setLeftBound( ((double)extend_left)/1000000.0); state[i].setRightBound( ((double)extend_right)/1000000.0); state[i].setBottomBound( ((double)extend_bottom)/1000000.0 ); state[i].setTopBound( ((double)extend_top)/1000000.0); /* printf("%s\n", state[i].getName()); printf("%f\n", state[i].getLeftBound()); printf("%f\n", state[i].getRightBound()); printf("%f\n", state[i].getBottomBound()); printf("%f\n", state[i].getTopBound()); */ } // for left_bound = state[0].getLeftBound();; right_bound = state[0].getRightBound(); bottom_bound = state[0].getBottomBound(); top_bound = state[0].getTopBound(); for ( int i = 1; i < numState; i++) { double bound; bound = state[i].getLeftBound(); if ( bound < left_bound ) left_bound = bound; bound = state[i].getRightBound(); if ( bound > right_bound ) right_bound = bound; bound = state[i].getBottomBound(); if ( bound < bottom_bound ) bottom_bound = bound; bound = state[i].getTopBound(); if ( bound > top_bound ) top_bound = bound; } printf("left_bound = %f\n", left_bound); printf("right_bound = %f\n", right_bound); printf("bottom_bound = %f\n", bottom_bound); printf("top_bound = %f\n", top_bound); } // getUSBoundary() /* Close all sockets before the forced quit caused by signal */ void signal_handler(int n) /* Chee, 7/23/01: changed from "void signal_handler()". See child_end(int) for explanation of similar change. */ { close(con_sock); close(server_sock); exit(0); } /* When the state of a child process is changed, (for example, it is terminated, or ended by call exit(),) the server should call wait() to get the state. This will prevent the child process from becoming a zombie process when it has finished. */ void child_end(int n) /* Chee, 7/23/01: changed from "void child_end()". But we do nothing with the argument n. Note that child_end is the second argument to sigset(int, func) (see below). In the latest /usr/include/signal.h, the second argument to sigset(int, func) must by a function(int) returning void. */ { wait(NULL); } void init_servconnection() { struct sockaddr_in server; /* STEP (A). Creating socket */ server_sock = socket(PF_INET, SOCK_STREAM, 0); // it is misconception to use "AF_INET" instead of "PF_INET" if (server_sock < 0) { perror("socket"); exit(1); } server.sin_family = PF_INET; server.sin_port = htons(srv_port); server.sin_addr.s_addr = INADDR_ANY; /* STEP (B). Bind the specified port to this socket */ if (bind(server_sock, (struct sockaddr *) & server, sizeof(server)) < 0) { perror("bind socket"); exit(1); } /* listen for connection */ if (listen(server_sock, 5) < 0) { perror("listen"); exit(1); } } void usage() { fprintf(stderr, "usage homesrvd [-p port]\n"); exit(1); } extern int errno; /* handle_req() will get input from the client, parse it and write the result back to the client. In this case, it will accept a number, either integer or float-point value, and return twice the number. It will repeat until the input is string "quit". */ void handle_req() { char buff[8192], out[commandMax]; int lg, flag, srv1, result_i; char *filename, *c, *p; struct stat statres; char req[commandMax]; double result_f; double rectangle[4]; int counter=0; int transDone=0; //if finished from result to TLineBuff flag = 1; numBlock=0; printf("Begin to recieve command\n"); while (flag){ lg = read(con_sock, req, commandMax); if (lg == -1 && errno == EBADF) goto error; //printf("received:%s\n",req); /* Jump out Loop, begin to serve Map data*/ if (counter>=4){ flag = 0; break; } if (req[lg - 1] != '\n' || req[lg - 2] != '\r') { sprintf(req, "1 Error: Unknown input 1\r\n"); write(con_sock, req, strlen(req)); continue; } /* Get rid of the trailing new line character and carriage return character. */ req[lg - 2] = '\0'; /* Get the first part of the line only. (Separated by space.) */ c = strtok(req, " "); /* Empty line */ if (c == NULL) { sprintf(req, "2 Error: Unknown input 2\r\n"); write(con_sock, req, strlen(req)); continue; } /* quit */ if (strncmp(c, "quit", 4) == 0) { flag = 0; break; } result_f = atof(c); sprintf(req, "%f\r\n", result_f); write(con_sock, req, strlen(req)); rectangle[counter]=atof(c); counter++; }//while (flag) // *********************** // readData(rectangle[0],rectangle[1],rectangle[2],rectangle[3]); resultTLine = (Line*)malloc(MAX_POINTS*sizeof(Line)); /* printf("x_left=%f\n", rectangle[0]); printf("x_right=%f\n", rectangle[1]); printf("y_top=%f\n", rectangle[2]); printf("y_bottom=%f\n", rectangle[3]); */ getTLine(rectangle[0],rectangle[1],rectangle[2],rectangle[3]); printf("%d\n", total_tline_num); printf("The data has been processed, transmitting...\n"); //Begin to send map data to client. Send one block, read an response, use "done" to finish transmit. flag=1; transDone=0; counter=0; do { /*copy result to TLineBuff*/ TLineBuff[0]='\0'; while ((strlen(TLineBuff)<(buffMax-100))&&(counter=total_tline_num){ transDone=1; } }while(flag); /* Some connection error happened, or quit the loop because receiving "quit" from the client. Will close connection and exit this function. */ error: close(con_sock); free(resultTLine); printf("finished, blocks=%d\n",numBlock); } void attenteconnection() { int lg, pid; lg = sizeof(struct sockaddr_in); /* repeat until accept a successful connect */ do{ con_sock = accept(server_sock, (struct sockaddr *) & source, &lg); printf("server:got connection from %s\n",inet_ntoa(source.sin_addr)); }while (con_sock <= 0); /* Fork a child process to serve the client */ //if ((pid = fork()) != 0) //{ /* parent process can close the connect and quit */ // close(con_sock); //} //else //{ /* The child process will handle the client, and the quit when finished. */ printf("the child process\n"); handle_req(); close(con_sock); // exit(1); //} } main(int argc,char **argv) { int lg; /* Shift the parameter */ argc--; argv++; while (argc > 0) { if (argv[0][0] != '-') usage(); switch (argv[0][1]) { case 'p': /* Set port number of the server */ srv_port = atoi(argv[1]); argv += 2; argc -= 2; break; default: usage(); } } /* Intercept CHILD signal. This signal occurs when a child process changes its status. In this program, it usually means when a child process calls exit() to end itself. */ // sigset(SIGCHLD, child_end); signal(SIGCHLD, child_end); /*Chee, 7/23/01: in latest /usr/include/signal.h, child_end must by a function(int) returning void. */ /* Intercept some signals which will end this process so we can close connection before quit it. */ signal(SIGTERM, signal_handler); signal(SIGQUIT, signal_handler); signal(SIGINT, signal_handler); // initialization getUSBoundary(); for ( int j = 0; j < numState; j++) { state[j].setName(stateName[j]); strcpy(file_name, map_dir); strcat(file_name, "/"); strcat(file_name, state[j].getName()); strcat(file_name, file_suffix); state[j].readStateMap(file_name); } /* Setup the socket and the port */ init_servconnection(); printf("The server is ready!\n"); /* Wait for connection */ do { attenteconnection(); } while (1); }