Использованные источники

Московский Государственный Институт Электроники и Математеки

Кафедра ИКТ

 

Курсовая работа по предмету:

Сетевые технологии.

Тема работы:

Распределенная служба кодирования

 

Выполнил

студент группы С-64

Белехов В

 

Принял

Орлов Петр

 

 

Москва 2009 год

Список исполнителей

Белехов Владимир Николаевич – Выполнял работу.

Андреев Дмитрий Рубенович – Подготовил постановку задачи и техническое задание.

Сагратян Асатур Ашаотович – Помощь, google.

Реферат

Ключевые слова:

Распределеный, кодирование, клиент-сервер, база данных.

Приложения:

Листинги: сервер-приложение, клиент-приложение, конфиги к ним, кодирующий скрипт.

Источники: для работы с mysql, libcurl.

 

Цель работы: Разработать клиент-серверное приложение распределенния задач кодирования.

Методолгия:Научный тык.

Степень внедрения: Отладка.

Область применения: кодирование видео.

Значимость работы: повышает эффективность кодирования видео, сервером СОВА

Оглавление

Список исполнителей.. 2

Реферат. 3

Оглавление. 4

Сокращения.. 5

Постановка задачи.. 6

Основная часть.. 7

Выбор средств разработки.. 7

Описание работы службы... 8

Сервер-приложение. 8

Клиент-приложение. 10

Заключение. 12

В ней реализованы:. 12

Требуется реализовать:. 12

Использованные источники.. 13

Приложения.. 14

Сервер-приложение server.c. 14

server.conf. 19

Кодирующий скрипт encode_script.sh.. 19

Клиент-Приложение client.c. 20

client.conf. 26

MySQL dump тестовой базы данных. 27

 

Сокращения

 

СОВА – Система Организации Видео Архива

РСК – Распределенная Служба Кодирования

Постановка задачи

Система Организации Видео Архива (СОВА) на каждый добавленный видеофайл, помимо изображений (раскадровка и превью-кадр) создаётся потоковая веб версия (h.264, x264, mp4) и прокси копия - копия низкого разрешения (mpeg4, DivX). Это накладывает на сервер большую нагрузку по кодированию видео, например h.264 версия кодируется 2-3 риалтайма. При этом в массе своей видеофайлы небольшой длины, однако количество их велико. Для разгрузки сервера и ускорения кодирования целесообразно делегировать задачи по кодированию различным компьютерам (например простаивающим в ночное время машинным залам кафедры). Это и является задачей разрабатываемой системы.

Основная часть

Выбор средств разработки

Для того чтобы распределять задачи целесообразно использовать клиент-серверную архитектуру. Поэтому мы выбрали для работы операционную систему Linux, язык программирования C++.

Для работы со списком задач была выбрана СУБД MySQL, т.к. Ее уже использует СОВА, и РСК как ее служба тоже будет использовать MySQL. С базой данных из приложения мы будем работать с помощью разработанной библиотеки языка С/C++ libmysql (mysql.h, myglobal.h и другие)

Задача, которую получают клиенты содержит: ссылку на файл для обработки и параметры его кодирования. По полученной ссылке файл будет скачан с существующего FTP сервера кафедры. Для решения этой задачи мы использовали библиотеку языка С/C++: libcurl. Также мы будем использовать эти библиотеки при загрузке уже закодированного видео обратно на FTP сервер СОВЫ.

Кодирование будет осуществлять shell скрипт запускаемый из клиент-приложение. Разработка самого скрипта не входит в мое тз, однако я должен обеспечить его исполнение на этапе кодирования видео.

Описание работы службы

Сервер-приложение

Забирает из конфигурационного файла параметры для: налаживания клиент-серверного соединения (порт соединения), параметры соединения с базой данных задач кодирования: адрес, логин, пароль, порт пользователя СУБД MySQL. Для этого открываем конфигурационный файл. Каждый параметр помечен конструкцией типа ***имя_параметра. Это сделано чтобы впоследствии было легко разобратся где какие параметры

config = fopen("server.conf", "r")

do {

non_infiniti++; // подстраховка, чтобы цикл не ушел в вечную петлю если не окажется корректного                                       // подтверждения конца файла

fgets(buf, FILELINE, config);

// берем из конфига порт

if(strcmp(buf, "***port\n") == 0) {

fgets(buf, FILELINE, config);

SERV_PORT = atoi(buf);

continue; }

......

} while (non_infiniti < 1000);

Соединение с базой данных из которой мы будем получать задачи:

инициация структуры базы данных, если нет необходимых библиотек произойдет ошибка

rskdb = mysql_init(NULL);                

непосредственно соединение с базой данных по параметрам, полученным из конфига

mysql_real_connect(rskdb, mysql_host, mysql_user, mysql_pass, mysql_db, mysql_port, NULL, 0)

 

Запускает прослушивающий сокет, ожидающий присоединения клиентов-кодировщиков.

Это происходит путем выхова трех комманд:

1) создания интернет сокета fdserver = socket(AF_INET, SOCK_STREAM, 0)

AF_INET означает что мы исползуем протокол IPv4

SOCK_STREAM – используется транспортный протокол TCP, а не UDP (DATAGRAM)

2) bind(fdserver, (struct sockaddr *) &servaddr, sizeof(servaddr))

3) listen(fdserver, 1024)

При присоединении клиента, совершает опрос базы данных задач на предмет наличиия задач кодирования.

Command = = "SELECT * FROM goal WHERE at_work = 0";

mysql_query((MYSQL *)rskdb, command);

Если таковые полученны он забирает задачу из бд на кодирование, отправляет ее клиенты, и ожидает результата работы клиенты – флаг успешного окончания, не успеха выполнения задачи. С помощью этого можно определить корректность выполнения задач клиентами-кодировщиками.

table = mysql_store_result((MYSQL *)rskdb);

if(table == NULL) {

printf("Error: can't get the result description\n");

send(fdclient, "exit", MAXLINE, 0);

break; }

if(mysql_num_rows(table) > 0) {

row = mysql_fetch_row(table);

sendlink = row[1];

sendname = row[3];

Оттданые задачи отмечаем, для того чтобы не раздать на кодирование одни и тежи файлы

mysql_query((MYSQL *)rskdb, UPDATE rsk.goal g SET at_work = 1 WHERE link “sendlink”);

send(fdclient, sendname, MAXLINE, 0);

send(fdclient, sendlink, MAXLINE, 0);

 

Если задачи кончились – клиенты отсылается флаг успешного окончания работы.

send(fdclient, "exit", MAXLINE, 0);

 

Клиент-приложение

Забирает из конфигурационного файла пармаетры: соединения с сервером (адрес и порт сервера); соединения с FTP севером (логин пароль).

Коннектится к серверу.

fdclient = socket (AF_INET, SOCK_STREAM, 0);

connect(fdclient, (struct sockaddr *) &servaddr, sizeof(servaddr);

Планируется что кодирующий скрипт будет также скачеватся с ftp сервера, это позволит облегчить вопрос обновления системы – один раз изменив кодирующий скрипт на серверы, все клиенты будут сами обновлятся. Поэтому выполним команду выдачи прав на исполнение нашего кодирующего bash-скрипта.

system(“cmod +x SCRIPT “);

Получает от сервера задачу кодирования.

recv(fdclient, recvflag, MAXLINE, 0);

recv(fdclient, recvlink, MAXLINE, 0);

 

Обрабатывает задачу:

1. По полученной ссылке загружает с FTP сервера файл для кодирования

curl_easy_setopt(curl, CURLOPT_URL, recvlink);

curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);

2. Запускает кодирующий скрипт

system("./ SCRIPT  recvname newname MYTMP encode_threads ");

3. Загружает закодированный файл на FTP сервер.

curl = curl_easy_init();

curl_easy_setopt(curl,CURLOPT_URL, "ftp:// ftp_login:ftp_pass@ftp_link/newname”);

4. Удаляет временные файлы.

system("rm recvname");

 


Это повторяется до тех пор пока не придет флаг что у сервера кончились задачи кодирования.

if(strcmp(recvflag, "exit") == 0) {

send(fdclient, "exit", MAXLINE, 0);

break; }


Заключение

Написана бэта-версия клиент-серверного приложения.

В ней реализованы:

1. Соединиение клиента и сервера;

2. Работа клиента с тестовой базой данных;

3. Пересылка задач от сервера к клиенту, и ответ клиента о степени выполнения задачи (успешно не успешно, как каком этапе произошла ошибка (загрузка, кодирование, выгрузка));

4. Скачивание и закачивание с FTP сервера файлов;

5. Имеется тестовый кодирующий скрипт, получающий все необходимые параметры, которые будут в дальнейшем использованы.

Требуется реализовать:

1. Перенести на реальную базу данных задач. Не выполнено так как мне еще не дали к ней доступ.

2. Обеспечить коннект к нестандартному порту FTP сервера. Не выполнено, т.к. Этого не было в тз.

3. Написать кодирующий скрипт. Не выполнено, т.к. Это следующий этап работы.

 

Использованные источники

1. Стивенс У.Р. “Unix Разработка сетевых приложений” 2003г.

2. Руководство по работе с библиотеками libmysql

http://leithal.cool-tools.co.uk/sourcedoc/mysql509/html/mysql_8h.html

3. Пример использования библиотек libcurl (скачивание)

http://curl.haxx.se/lxr/source/docs/examples/ftpget.c

4. Пример использования библиотек libcurl (загрузка)

http://curl.haxx.se/lxr/source/docs/examples/ftpupload.c

5. Руководство по написанию bash скриптов

http://www.opennet.ru/docs/RUS/bash_scripting_guide/

Приложения

Сервер-приложение server.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <strings.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <time.h>

#include <errno.h>

#include <mysql.h>

#include <my_global.h>

#define MAXLINE 300

#define FILELINE 200

#define OPT_SIZE 1000

int main()

{

/** take config data **/

int SERV_PORT, mysql_port;

char mysql_host[FILELINE] = {}, mysql_user[FILELINE] = {}, mysql_pass[FILELINE] = {}, mysql_db[FILELINE] = {};

FILE *config;

char buf[FILELINE];

int buf_len = 0, non_infiniti = 0;

if ((config = fopen("server.conf", "r")) == NULL)

{

printf("\"server.conf\" fopen error\n");

return 1;

}

do

{

non_infiniti++; // подстраховка, чтобы цикл не ушел в вечную петлю

fgets(buf, FILELINE, config);

// берем из конфига порт

if(strcmp(buf, "***port\n") == 0)

{

fgets(buf, FILELINE, config);

SERV_PORT = atoi(buf);

continue;

}

if(strcmp(buf, "***mysql_host\n") == 0)

{

fgets(buf, FILELINE, config);

buf_len = strlen(buf);

strncpy(&mysql_host[0], buf, buf_len - 1);

continue;

}

if(strcmp(buf, "***mysql_user\n") == 0)

{

fgets(buf, FILELINE, config);

buf_len = strlen(buf);

strncpy(&mysql_user[0], buf, buf_len - 1);

continue;

}

if(strcmp(buf, "***mysql_pass\n") == 0)

{

fgets(buf, FILELINE, config);

buf_len = strlen(buf);

strncpy(&mysql_pass[0], buf, buf_len - 1);

continue;

}

if(strcmp(buf, "***mysql_database\n") == 0)

{

fgets(buf, FILELINE, config);

buf_len = strlen(buf);

strncpy(&mysql_db[0], buf, buf_len - 1);

continue;

}

if(strcmp(buf, "***mysql_port\n") == 0)

{

fgets(buf, FILELINE, config);

mysql_port = atoi(buf);

continue;

}

if (strcmp(buf, "***end\n") == 0)

break;

strcpy(buf, "");

} while (non_infiniti < 1000);

printf("%s\n", mysql_host);

printf("%s\n", mysql_user);

printf("%s\n", mysql_pass);

printf("%s\n", mysql_db);

printf("%d\n", mysql_port);

/** MySQL init **/

// Дескриптор соединения

MYSQL *rskdb;

// Дескриптор результирующей таблицы

MYSQL_RES *table;

// Дескриптор строки

MYSQL_ROW row;

rskdb = mysql_init(NULL);

if(rskdb == NULL)

{

// Если дескриптор не получен - выводим сообщение об ошибке

fprintf(stderr, "Error: can't create MySQL-descriptor\n");

exit(1);

}

// Подключаемся к серверу

// потом добавим подцепление из конфига

if(!mysql_real_connect(rskdb,

mysql_host,

mysql_user,

mysql_pass,

mysql_db,

mysql_port, //3306,

NULL,

0

))

{

// Если нет возможности установить соединение с сервером

// базы данных выводим сообщение об ошибке

fprintf(stderr,

"Error: can't connect to database %s\n",

mysql_error(rskdb));

return 1;

}

else

{

// Если соединение успешно установлено выводим фразу - "Success!"

fprintf(stdout, "Success!\n");

}

// Устанавливаем кодировку соединения, чтобы предотвратить

// искажения русского текста

if(mysql_query((MYSQL *)rskdb, "SET NAMES 'utf8'")!= 0)

printf("Error: can't set character set\n");

/** creating listen socket **/

int fdserver, fdclient;

socklen_t client_len;

pid_t childpid;

struct sockaddr_in cliaddr, servaddr;

// сокет сервера

if ((fdserver = socket(AF_INET, SOCK_STREAM, 0)) < 0)

{

printf("cant make server socket\n");

return 1;

}

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

//servaddr.sin_addr.s_addr = inet_pton(AF_INET, RSK_SERV_ADDR, &servaddr.sin_addr);

servaddr.sin_port = htons(SERV_PORT);

char myaddr[INET_ADDRSTRLEN];

inet_ntop(AF_INET, &servaddr.sin_addr, myaddr, sizeof(myaddr));

printf("serv addres %s\nserv port %d\n", myaddr, SERV_PORT);

if ((bind(fdserver, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0)

{

printf("binding error\n");

close(fdserver);

return 1;

}


 

if ((listen(fdserver, 1024)) < 0)

{

printf("listening error\n");

close(fdserver);

return 1;

}

char strrecv[MAXLINE], *sendflag, *sendname, *sendlink, *command;

char SQL_QUESTION[] = "SELECT * FROM goal WHERE at_work = 0";

char SQL_UPDATE[] = "UPDATE rsk.goal g SET at_work = 1 WHERE link = \"";

//char *strsend

//strsend = (char *) malloc (sizeof(char) * MAXLINE);

command = (char *) malloc (sizeof(char) * MAXLINE);

sendflag = (char *) malloc (sizeof(char) * MAXLINE);

sendname = (char *) malloc (sizeof(char) * MAXLINE);

sendlink = (char *) malloc (sizeof(char) * MAXLINE);

for(;;)

{

client_len = sizeof(cliaddr);

if ((fdclient = accept(fdserver, (struct sockaddr *) &cliaddr, &client_len)) < 0)

{

printf("accepting error\n");

close(fdserver);

return 1;

}

if ((childpid = fork()) == 0) // дочерний процесс

{

/*** child ***/

close(fdserver); // закрываем прослушивающий сокет

/** send encoding script **/

int exitflag = 0;

do

{

// Выполняем SQL-запрос

strcpy(command, SQL_QUESTION);

if(mysql_query((MYSQL *)rskdb, command)!= 0)

{

printf("Error: can't execute SQL-query\n");

send(fdclient, "exit", MAXLINE, 0);

break;

}

 

// Получаем дескриптор результирующей таблицы

table = mysql_store_result((MYSQL *)rskdb);

if(table == NULL)

{

printf("Error: can't get the result description\n");

send(fdclient, "exit", MAXLINE, 0);

break;

}

 

// Если имеется хотя бы одна запись - выводим

// список каталогов

if(mysql_num_rows(table) > 0)

{

row = mysql_fetch_row(table);

sendlink = row[1];

sendname = row[3];

strcpy(command, SQL_UPDATE); //... "

strcat(command, sendlink); // link

strcat(command, "\""); // "

mysql_query((MYSQL *)rskdb, command);

send(fdclient, "next goal", MAXLINE, 0);

printf("next goal\n");

printf("I send this name: %s\n", sendname);

send(fdclient, sendname, MAXLINE, 0);

printf("I send this link: %s\n", sendlink);

send(fdclient, sendlink, MAXLINE, 0);

}

else

{

send(fdclient, "exit", MAXLINE, 0);

exitflag = 1;

printf("Задачи кончились!!! bingo gl hf\n");

break;

}

 

 

// Освобождаем память, занятую результирующей таблицей

mysql_free_result(table);

// тут мы сможем узнать удачно завершилось кодирование или нет

recv(fdclient, strrecv, MAXLINE, 0);

printf("client answer %s\n", strrecv);

} while (exitflag!= 1);

close(fdserver);

exit(0);

}

}

/** end **/

// Закрываем соединение с сервером базы данных

mysql_close(rskdb);

close(fdserver);

return 0;

}


Server.conf

***port

2011

***mysql_host

localhost

***mysql_user

rsk

***mysql_pass

123

***mysql_database

rsk

***mysql_port

3306

 

***end


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: