Добавил:
nickolai_oreschenko
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:УТС 4 семестр / Lab9_Oreshchenko / server
.cpp#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