Скачиваний:
6
Добавлен:
08.08.2022
Размер:
6.52 Кб
Скачать
#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include "string.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "arpa/inet.h"
#include "netinet/in.h"
#include "pthread.h"
#include "sys/utsname.h"
#include "fcntl.h"
#include <queue>		// очереди
#include <sys/resource.h>	// getrlimit()


#define SERVER_PORT     8080
#define CLIENT_PORT     7070
#define BUFSIZE         64

int sockfd;			// дескриптор сокета
struct sockaddr_in cli_addr;	// "адрес" клиента
socklen_t addr_len;		// размер "адреса" клиента
bool go_receive;		// флаг потока получения запросов
bool go_handle;			// флаг потока обработки запросов
bool go_response;		// флаг потока отправки ответов

std::queue<char*> req;		// очередь запросов
std::queue<char*> res;		// очередь ответов

pthread_mutex_t * reqMutex;	// мьютекс очереди запросов
pthread_mutex_t * resMutex;	// мьютекс очередь ответов

// Поточная функция принятия запросов
void * receive(void * arg){
	char buffer[ BUFSIZE ];

	// Основная программа
	while(go_receive){
		
		// Читаем запросы клиента с сокета
		int bytes = recvfrom(sockfd, (char *) buffer, BUFSIZE, 
						              0, 
							      (struct sockaddr *) &cli_addr,
							      &addr_len);
		
		// Считали ?
		if( bytes > 0 )
		{
			buffer[bytes] = '\0';
			
			// Захватываем мьютекс
			pthread_mutex_lock( reqMutex );

			req.push(buffer);
			
			// Освобождаем мьютекс
			pthread_mutex_unlock( reqMutex );
			
			printf(" Data received: %s. Request added to queue \n", buffer);
		}
		else {
			perror("Receive error");
			sleep(2);
		}

		sleep(1);
	}

	pthread_exit(NULL);
}

// Поточная функция обработки запросов
void * handle(void * arg){
	
	// По заданию будем отправлять клиенту информацию о лимите ресурсов
	// в нашем случае используем RLIMIT_NPROC 
	// Информация о максимальном количестве процессов, которое может создать вызывающий процесс
	
	// сначала получим её в структуру
	struct rlimit info;
	
	if(getrlimit(RLIMIT_NPROC, &info) == -1){
		perror("getrlimit()");
		sleep(1);
	}

	char msg[ BUFSIZE ];
	sprintf(msg, " Max number of extant processes: %d",(int) info.rlim_max);

	// Основная программа
	while(go_handle){
		
		// Захватываем очередь запросов
		pthread_mutex_lock(reqMutex);

		// Есть ли запросы ?
		if(!req.empty()){
			req.pop();// удаляем запрос из очереди
			
			// Освобождаем очередь запросов
		  	pthread_mutex_unlock( reqMutex );
			
			// Захватываем очередь ответов
			pthread_mutex_lock(resMutex);
			
			res.push(msg);	// добавляем ответ в очередь
			
			// Осовобождаем очередь ответов
			pthread_mutex_unlock( resMutex );
		}
		else {
			// Освобождаем очередь запросов
		  	pthread_mutex_unlock( reqMutex );
			printf(" Requests are out \n");
		}

		sleep(1);
	}

	pthread_exit(NULL);
}

// Поточная функция отправки ответов
void * response(void * arg){
	
	// Основная программа
	while(go_response){
		
		// Захватываем мьютекс очереди ответов
		pthread_mutex_lock(resMutex);

		// Пустая ли очередь ответов ?
		if(!res.empty()){
			// Вытаскиваем ответ из очереди
			char msg[BUFSIZE] = {0};
			strcpy(msg, res.front());
			res.pop();
		
			// Освобождаем мьютекс очереди ответов
			pthread_mutex_unlock( resMutex );	
			
			// Посылаем ответ клиенту
			int bytes = sendto(sockfd,(const char *) msg, 
				    		  strlen(msg), 
				      		  0, 
				      		  (struct sockaddr *) &cli_addr, 
				      		  addr_len);
			
			// Удачно?
			if(bytes > 0 )	{
				printf(" Respose:<%s> was sent \n", msg);
			}
			else {
				perror(" Send error");
				sleep(1);
			}
		}
		else pthread_mutex_unlock(resMutex);
		
		sleep(1);
	}

	pthread_exit(NULL);
}


int main(int argc, char * argv[]){
	printf(" Server started \n");

	// Создаём сокет (файловый дескриптор)
	if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
		perror( " socket()");
		exit(EXIT_FAILURE);
	}
	
	// Делаем сокет неблокирующимся
	int flags = fcntl(sockfd, F_GETFL);
	flags |= O_NONBLOCK;
	fcntl(sockfd, F_SETFL, flags);

	// Инициализируем мьютексы
	reqMutex = new pthread_mutex_t;
	pthread_mutex_init(reqMutex, NULL);

	resMutex = new pthread_mutex_t;
	pthread_mutex_init(resMutex, NULL);

	// Заполняем информацию о сервере
	struct sockaddr_in serv_addr;

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERVER_PORT);
	serv_addr.sin_addr.s_addr = htonl( INADDR_ANY );

	// Задаём адрес клиента  
        struct sockaddr_in cli_addr;

        cli_addr.sin_family = AF_INET;
        cli_addr.sin_port = htons( CLIENT_PORT );
        cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	
	addr_len = sizeof(cli_addr);

	// Привязываем сокет к адресу сервера
	if( bind(sockfd, (const struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
		perror(" bind()");
		exit(EXIT_FAILURE);
	}
	
	int optval = 1;
   	setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
	
	// Создаём потоки
	pthread_t tid[3];

	go_receive = go_handle = go_response = true;

	pthread_create(&tid[0], NULL, &receive, NULL);
	pthread_create(&tid[1], NULL, &handle, NULL);
	pthread_create(&tid[2], NULL, &response, NULL);

	getchar();
	go_receive = go_handle = go_response = false;
	
	// Ждём завершения потоков
	for(int i = 0; i < 3; i++)
		pthread_join(tid[i], NULL);

	// Закрываем сокет
	close(sockfd);

	// Удаляем мьютексы
	pthread_mutex_destroy( reqMutex );
	pthread_mutex_destroy( resMutex );

	printf(" Server ended \n");
	exit(EXIT_SUCCESS);
}
Соседние файлы в папке Lab9_Oreshchenko
  • #
    08.08.202217.67 Кб3client
  • #
    08.08.20223.54 Кб6client.cpp
  • #
    08.08.2022124 б4script.client
  • #
    08.08.2022124 б5script.server
  • #
    08.08.202242.34 Кб3server
  • #
    08.08.20226.52 Кб6server.cpp