Beispiel #1
0
int main(int argc, char *argv[])
{
	pthread_t tid;
	int srv_sock = sockcreate(PORT);
	if (srv_sock == -1) {
		printf("Couldn't create socket.\n");
		exit(1);
	}
	pthread_mutex_init(&mutex, NULL);
	printf("Hey-Server activating on port %ld.\n", PORT);

	signal(SIGINT, cleanup);

	while (1) {
		int cl_sock = sockaccept(srv_sock);
		printf("Connection request received.\n");
		pthread_create(&tid, NULL,
				   (void*) &receive, (void*) cl_sock);
	}
	cleanup(0);
	return 0;
}
Beispiel #2
0
/*
 * This is the main thread
 * Its role consists in accepting connections to the server,
 * and placing the new clients in a client queue where they will wait to
 * be processed by the manager threads
 */
int ntqserver(int verbose, char* address, int port, int n_queues, int n_managers) {
	int ret = 0;
	int i;
	ntqs_server* ntqs;
	ntqs_manager* managers;
	ntqs_manager* manager;
	pthread_mutex_t m_console_data;
	pthread_mutex_t m_clients_data;
	pthread_mutex_t* m_queues_array;
	pthread_mutex_t* m_interrupt_array;
	ntqs_client* client = NULL;


	printf("Starting server ...\n");

	ntqs = (ntqs_server*)malloc(sizeof(ntqs_server));
	if (ntqs == NULL) {
		fprintf(stderr, "ntqserver(): error not enough memory\n");
		return -1;
	}

	ntqs->verbose = verbose;
	/**
	 *  Verbosity parameter
	 */
	ntqs->host_address = address;
	/**
	 *  This is the address on which the server listens.
	 */
	ntqs->host_port = port;
	/**
	 *  This is the server port number
	 */
	ntqs->n_queues = n_queues;
	/**
	 *  This is the number of queues (specified by the -q parameter) that will be created and accessible
	 */
	ntqs->n_managers = n_managers;
	/*
	 *  This is the number of manager threads that can be created to process clients.
	 *  1 (the default value) should be sufficient in most cases.
	 *  A higher number may give some speed ups only if there are many connections and/or clients need to transmit a lot of data.
	 */
	ntqs->socket = 0;
	/**
	 *  This is the server main socket used for accepting connections only
	 */
	ntqs->m_console = NULL;
	/**
	 *  This is a console mutex used to prevent more than one thread at time from printing to the console
	 */
	ntqs->q_clients = NULL;
	/**
	 *  This is the client queue
	 *  The manager threads are regularly popping clients from the queue in order to process them
	 *  or pushing them back to the queue once they are done processing them.
	 *  New clients are added to the queue, and disconnecting clients leave the queue.
	 */
	ntqs->m_clients = NULL;
	/**
	 *  This mutex is there to allow only one manager at a time to interact with the client queue
	 */
	ntqs->m_queues = NULL;
	/*
	 *  All task queues are mutex protected so that only one manager can push or pop data from a given queue at a given time
	 */
	ntqs->queues = NULL;
	/**
	 *  This is the array of the n_queues task queues
	 */


	// creating client queue mutex
	ntqs->m_clients = &m_clients_data;
	ret = pthread_mutex_init(ntqs->m_clients, NULL);
	if (ret != 0) {
		fprintf(stderr, "ntqserver(): error mutex creation failed\n");
		return -1;
	}
	// creating client queue
	ret = llq_create(&ntqs->q_clients);
	if (ret != 0) {
		fprintf(stderr, "ntqserver(): error queue creation failed\n");
		return -1;
	}



	// creating queues mutexes
	ntqs->m_queues = (pthread_mutex_t**)malloc(ntqs->n_queues * sizeof(pthread_mutex_t*));
	if (ntqs->m_queues == NULL) {
		fprintf(stderr, "ntqserver(): error not enough memory\n");
		return -1;
	}
	m_queues_array = (pthread_mutex_t*)malloc(ntqs->n_queues * sizeof(pthread_mutex_t));
	if (m_queues_array == NULL) {
		fprintf(stderr, "ntqserver(): error not enough memory\n");
		return -1;
	}
	for (i = 0; i < ntqs->n_queues; i++) {
		ntqs->m_queues[i] = &m_queues_array[i];
		ret = pthread_mutex_init(ntqs->m_queues[i], NULL);
		if (ret != 0) {
			fprintf(stderr, "ntqserver(): error mutex creation failed\n");
			return -1;
		}
	}
	// creating queues
	ntqs->queues = (llq**)malloc(ntqs->n_queues * sizeof(llq*));
	if (ntqs->queues == NULL) {
		fprintf(stderr, "ntqserver(): error not enough memory\n");
		return -1;
	}
	for (i = 0; i < ntqs->n_queues; i++) {
		ret = llq_create(&ntqs->queues[i]);
		if (ret != 0) {
			fprintf(stderr, "ntqserver(): error queue creation failed\n");
			return -1;
		}
	}


	/**
	 * Create a server socket
	 */
	ret = socktcp(&ntqs->socket);
	if (ret < 0) {
		fprintf(stderr, "ntqserver(): error socket creation failed\n");
		return -1;
	}

	/**
	 * Bind and listen
	 */
	ret = socklisten(ntqs->socket, ntqs->host_address, ntqs->host_port, 10);
	if (ret < 0) {
		fprintf(stderr, "ntqserver(): error socket listen failed\n");
		return -1;
	}

	printf("Listening on %s:%d ...\n", ntqs->host_address, ntqs->host_port);


	printf("Starting manager(s) ...\n");
	// setup multithreading

	// create console mutex
	ntqs->m_console = &m_console_data;
	ret = pthread_mutex_init(ntqs->m_console, NULL);
	if (ret != 0) {
		fprintf(stderr, "ntqserver(): error console mutex creation failed\n");
		return -1;
	}

	// create interrupt mutexes array
	m_interrupt_array = (pthread_mutex_t*)malloc(ntqs->n_managers*sizeof(pthread_mutex_t));
	if (m_interrupt_array == NULL) {
		pthread_mutex_lock(ntqs->m_console);
		fprintf(stderr, "ntqserver(): error not enough memory\n");
		pthread_mutex_unlock(ntqs->m_console);
		return -1;
	}


	// create managers
	managers = (ntqs_manager*)malloc(ntqs->n_managers*sizeof(ntqs_manager));
	if (managers == NULL) {
		pthread_mutex_lock(ntqs->m_console);
		fprintf(stderr, "ntqserver(): error not enough memory\n");
		pthread_mutex_unlock(ntqs->m_console);
		return -1;
	}


	for (i = 0; i < ntqs->n_managers; i++) {
		manager = &managers[i];
		manager->ntqs = ntqs;
		manager->id = i;
		manager->m_interrupt = &m_interrupt_array[i];
		manager->interrupt = 0;

		ret = pthread_mutex_init(manager->m_interrupt, NULL);
		if (ret != 0) {
			pthread_mutex_lock(ntqs->m_console);
			fprintf(stderr, "ntqserver(): error interrupt mutex creation failed\n");
			pthread_mutex_unlock(ntqs->m_console);
			return -1;
		}

		/**
		 *  Start a manager thread
		 */
		ret = pthread_create(&manager->thread, NULL, &ntqmanagerwrapper, (void*)manager);
		if (ret != 0) {
			pthread_mutex_lock(ntqs->m_console);
			fprintf(stderr, "ntqserver(): error thread creation failed\n");
			pthread_mutex_unlock(ntqs->m_console);
			return -1;
		}
	}


	pthread_mutex_lock(ntqs->m_console);
	printf("Accepting connections ...\n");
	pthread_mutex_unlock(ntqs->m_console);

	while (1) {
		pthread_mutex_lock(ntqs->m_console);
		fflush(stderr);
		fflush(stdout);
		pthread_mutex_unlock(ntqs->m_console);

		// create new client data structure
		client = (ntqs_client*)malloc(sizeof(ntqs_client));
		if (client == NULL) {
			pthread_mutex_lock(ntqs->m_console);
			fprintf(stderr, "ntqserver(): error not enough memory\n");
			pthread_mutex_unlock(ntqs->m_console);
			return -1;
		}

		// check for server socket activity
		ret = sockreadable(ntqs->socket);
		if (ret < 0) {
			pthread_mutex_lock(ntqs->m_console);
			fprintf(stderr, "ntqserver(): error socket accept failed\n");
			pthread_mutex_unlock(ntqs->m_console);
			return -1;
		}

		if (ret == 0) {
			// socket idle (no new connection received)
			UTLsleep(10); // nothing to do so go to sleep
			// check for interrupt signal after sleeping (likely to happen while sleeping)
			if (signal_interrupt) {
				break;
			}
		}
		else {
			// activity on socket -> accept new connection and write to the client data structure
			ret = sockaccept(ntqs->socket, &client->socket, client->remote_ip, &client->remote_port);
			if (ret < 0) {
				pthread_mutex_lock(ntqs->m_console);
				fprintf(stderr, "ntqserver(): error socket accept failed\n");
				pthread_mutex_unlock(ntqs->m_console);
				return -1;
			}

			pthread_mutex_lock(ntqs->m_console);
			printf("%s:%d connected\n", client->remote_ip, client->remote_port);
			pthread_mutex_unlock(ntqs->m_console);


			//pthread_mutex_lock(ntqs->m_console);
			//printf("%s:%d in queue\n", client->remote_ip, client->remote_port);
			//pthread_mutex_unlock(ntqs->m_console);

			// from there on the client data becomes the property of the manager (unavalaible from the main thread)
			pthread_mutex_lock(ntqs->m_clients);
			llq_push(ntqs->q_clients, (void*)client);
			pthread_mutex_unlock(ntqs->m_clients);
		}
	}


	pthread_mutex_lock(ntqs->m_console);
	printf("Stopping server ...\n");
	pthread_mutex_unlock(ntqs->m_console);

	if (signal_interrupt) {
		/*
		 * Send interrupt signal to all the manager threads.
		 */
		for (i = 0; i < ntqs->n_managers; i++) {
			manager = &managers[i];
			pthread_mutex_lock(manager->m_interrupt);
			manager->interrupt = 1;
			pthread_mutex_unlock(manager->m_interrupt);
		}
	}


	/**
	 * Wait for threads to end
	 */
	for (i = 0; i < ntqs->n_managers; i++) {
		manager = &managers[i];
		ret = pthread_join(manager->thread, NULL);
		ret = pthread_mutex_destroy(manager->m_interrupt);
	}

	/**
	 * Free all data
	 */

	free((void*)managers);
	free((void*)m_interrupt_array);
	ret = pthread_mutex_destroy(ntqs->m_console);
	for (i = 0; i < ntqs->n_queues; i++) {
		while (!llq_isempty(ntqs->queues[i])) {
			free(llq_pop(ntqs->queues[i]));
		}
		llq_delete(&ntqs->queues[i]);
		ret = pthread_mutex_destroy(ntqs->m_queues[i]);
	}
	free((void*)m_queues_array);
	free((void*)ntqs->queues);
	while (!llq_isempty(ntqs->q_clients)) {
		client = (ntqs_client*)llq_pop(ntqs->q_clients);
		sockclose(client->socket);
		free(client);
	}
	sockclose(ntqs->socket);
	free((void*)ntqs->m_queues);
	llq_delete(&ntqs->q_clients);
	ret = pthread_mutex_destroy(ntqs->m_clients);

	free((void*)ntqs);

	return 0;
}