/** * Name: initializeSocket * Description: Binds a socket and begins listening to it for the web server. * * @param ipaddress IP Address * @param port Port Number */ int initializeSocket(const char * ipaddress, const char * port) { /* sets up struct to contain critical ip info*/ struct addrinfo hints; struct addrinfo * serverinfo; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; //Gets the necessary information such as ipaddress/port if (getaddrinfo(ipaddress, port, &hints, &serverinfo) != 0) { __android_log_print(ANDROID_LOG_ERROR,TAG,"Failed to get server info", 1); __android_log_print(ANDROID_LOG_ERROR,TAG,"%s %s", ipaddress,port); exit(1); } __android_log_print(ANDROID_LOG_INFO,TAG,"Creating Socket"); //initialize socket int sock = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol); if (sock < 0) { __android_log_print(ANDROID_LOG_ERROR, TAG, "Socket initialization failed", 1); __android_log_print(ANDROID_LOG_ERROR, TAG, strerror(errno), 1); endServer(sock, serverinfo, 0); } int yes =1; //Rebind socket if in use if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { __android_log_print(ANDROID_LOG_ERROR, TAG, "setsockopt"); exit(1); } __android_log_print(ANDROID_LOG_INFO,TAG,"Binding Socket"); //Bind Socket to ip address if (bind(sock, serverinfo->ai_addr,serverinfo->ai_addrlen) < 0) { __android_log_print(ANDROID_LOG_ERROR, TAG, "Socket Binding Failed", 1); endServer(sock, serverinfo, 0); } __android_log_print(ANDROID_LOG_INFO,TAG,"Listening to socket"); //Listen to 10 requests at a time if (listen(sock, 10) < 0) { __android_log_print(ANDROID_LOG_ERROR, TAG, "Socket listening failed", 1); endServer(sock, serverinfo, 0); } //release memory freeaddrinfo(serverinfo); return sock; }
/** * Name: runServer * Description: Runs the server. If a connection is accepted, then parent process continues listening * and spawns child process to process the message and close the connection to client. * * @param sock Socket File Descriptor for listening connection */ void runServer(int sock) { struct sockaddr_storage clientaddr; //continuous loop while (1) { socklen_t addr_size = sizeof(clientaddr); //accept the new connection int newsocket = accept(sock, (struct sockaddr*) &clientaddr, &addr_size); __android_log_print(ANDROID_LOG_INFO, TAG, "Accepting Socket"); if (newsocket < 0) { __android_log_print(ANDROID_LOG_ERROR, TAG, "Socket accepting failed", 1); __android_log_print(ANDROID_LOG_INFO, TAG, strerror(errno)); endServer(sock, NULL, newsocket); continue; } //split between parent process and child process. Parent=listening child=accepting if (!fork()) { close(sock); char buffer[HTTP_MAX_SIZE]; __android_log_print(ANDROID_LOG_INFO, TAG, "Receiving"); //grab info into httpReceive httpReceive(newsocket,buffer); __android_log_print(ANDROID_LOG_INFO,TAG,"%s %d", buffer, (int) strlen(buffer)); //kick back message up to java const char * message = processMessage(buffer); __android_log_print(ANDROID_LOG_INFO,TAG,"%s %d", message, (int) strlen(message)); __android_log_print(ANDROID_LOG_INFO, TAG, "Sending"); //get the message and send it to client if (send(newsocket,message,strlen(message), 0) < 0){ __android_log_print(ANDROID_LOG_ERROR,TAG,"Send Failed",1); endServer(-1, NULL, newsocket); } __android_log_print(ANDROID_LOG_INFO,TAG,"Sent Message %s", message); //close the new socket and exit the process close(newsocket); exit(0); } close(newsocket); } }
/** * Name: beginServer * Description: Binds a socket and begins listening to it for the web server. * * @param ipaddress IP Address * @param port Port Number */ void beginServer(const char* ipaddress, const char * port) { //initialize the socket int sock = initializeSocket(ipaddress, port); if(sock < 0) { endServer(sock, NULL, 0); } runServer(sock); }
/* * Singnal handler * http://www.csl.mtu.edu/cs4411.ck/www/NOTES/signal/install.html */ void INThandler(int sig) { //Interrupt Handler char c = '0'; if(sig != SIGINT){ //wenn Signal kein Interrupt ist (bsp. hangup) debugPrint("Signal is not SIGINT."); return; } else { infoPrint("Wollen Sie den Server wirklich beenden? [j/n]: "); c = getchar(); if((c == 'j') || (c == 'J')){ debugPrint("Server soll beendet werden."); endServer(); exit(0); } else { debugPrint("Server soll nicht beendet werden."); return; } } }
void loadQuestions(char* name){ char* message; int loaded; // remove shared memorey shm_unlink(SHMEM_NAME); // LOAD_CMD_PREFIX - Katalog laden if(write(stdinPipe[1], LOAD_CMD_PREFIX, strlen(LOAD_CMD_PREFIX)) < strlen(LOAD_CMD_PREFIX)){ errorPrint("Senden der Nachricht über Pipe fehlgeschlagen"); endServer(); exit(0); } // aktiven Katalog uebergeben if(write(stdinPipe[1], name, strlen(name)) < strlen(name)){ errorPrint("Senden der Nachricht über Pipe fehlgeschlagen"); endServer(); exit(0); } // Zeilenumbruch zum Abschluss if (write(stdinPipe[1], "\n", 1) < 1) { errorPrint("Senden der Nachricht über Pipe fehlgeschlagen"); endServer(); exit(0); } // von Pipe lesen ob laden des Katalogs erfolgreich (LOAD_SUCCESS_PREFIX - Katalog mit SIZE Fragen geladen) message = readLine(stdoutPipe[0]); if(strcmp(message, LOAD_SUCCESS_PREFIX) != -1){ infoPrint("Kataloge eingelesen"); // The memmove() function copies n bytes from memory area src to memory area dest memmove(message, message + sizeof(LOAD_SUCCESS_PREFIX) - 1, 50); loaded = atoi(message); infoPrint("Anzahl an eingelesenen Fragen: %i", loaded); } else { errorPrint("Fragen konnten nicht geladen werden"); endServer(); exit(0); } // shm_open() creates and opens a new, or opens an existing, POSIX shared memory object. // returns file descriptor of -1 in case of error shmHandle = shm_open(SHMEM_NAME, O_RDONLY, 0); if(shmHandle == -1){ errorPrint("Konnte Shared Memory nicht erstellen / öffnen!"); endServer(); exit(0); } // Groesse ShareMemory = Anzahl Fragen * Groesse der Fragen shmLen = loaded * sizeof(Question); ftruncate(shmHandle, shmLen); /* * Um ein mittels shm_open geöffnetes Shared Memory Objekt nun tatsächlich verwenden zu können, muss * dieses in den Adressraum des Prozesses eingebunden werden. * Die Funktion mmap bindet eine Datei, ein Gerät oder ein Shared Memory Objekt in den Adressraum * des aufrufenden Prozesses ein. */ // mmap() creates a new mapping in the virtual address space of the calling process. // void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); shmData = mmap(NULL, shmLen, PROT_READ, MAP_SHARED, shmHandle, 0); if(shmData == MAP_FAILED){ errorPrint("Konnte Shared Memory nicht in Adressraum einbinden!"); endServer(); exit(0); } // SharedMemory setShMem(shmData); return; }
/** Start des Servers * param argc Anzahl der Startparameter * param argv Startparameter */ int main(int argc, char ** argv) { // Der Server soll auf dem lokalen System nur einmal gestartet werden koennen. setSingleInstance(SingleInstanceFile); setProgName(argv[0]); // verarbeite Parameter process_commands(argc, argv); // reagiere auf Signal, u.a. STRG + C signal(SIGINT, INThandler); // gebe Gruppennamen aus infoPrint("\n\nServer Gruppe 04 Stroh, Steinbinder, Strohm\n"); // Spielerverwaltung initialisieren initSpielerverwaltung(); // Socket erstellen server_socket = openServerSocket(server_port); if(server_socket == -1){ errorPrint("Server Socket konnte nicht erstellt werden!"); endServer(); exit(0); } // Loader starten + Kataloge laden int loader_start_result = startLoader(); if(loader_start_result != 0){ errorPrint("Fehler beim Starten des Loaders: %i", loader_start_result); endServer(); exit(0); } int loader_load_catalogs_result = loadCatalogs(); if(loader_load_catalogs_result != 0){ errorPrint("Fehler beim Laden der Kataloge: %i", loader_load_catalogs_result); endServer(); exit(0); } // http://pubs.opengroup.org/onlinepubs/7908799/xsh/sem_init.html // Semaphor fuer Spielerliste / Punktestand initialisieren sem_init(&semaphor_score, 0, 0); // Score thread starten pthread_t score_thread; if(pthread_create(&score_thread, NULL, (void*)&score_main, NULL) == -1){ errorPrint("Score_thread konnte nicht erstellt werden!"); endServer(); exit(0); } // starte Login-Thread pthread_t login_thread; if(pthread_create(&login_thread, NULL, (void*)login_main(server_socket), NULL) == -1){ errorPrint("Login_thread konnte nicht erstellt werden!"); endServer(); exit(0); } // beende Server endServer(); return 0; }