1. Описание архитектуры. Текущий протокол имеет следующие характеристики:
1) Клиент отправляет запрос на сервер, длина каждого запроса является переменной. Длина запроса указывается в первом INT.
2) Каждый сервер обычно предоставляет услуги нескольким клиентам. Например, TS необходимо одновременно предоставлять услуги CP и NP.
CP предоставляет услуги NP и другим CP, а также является клиентом других CP, TS и SP.
3) Когда каждый сервер обслуживает клиента, это обычно долгосрочно и включает в себя множество запросов-ответов туда и обратно.
Такая структура в основном предназначена для поддержки большого количества одновременных клиентских подключений. При наличии большого количества одновременных клиентских подключений независимо от того, используются ли потоки или процессы, эффективные службы не могут быть предоставлены, поэтому необходимо использовать select.
Режим опроса.
2. Описание базовой структуры данных: для каждого клиента необходимо сохранить некоторую информацию, соответствующую клиенту. Текущие CPnew.c, SPnew.c.
По сути, это то же самое, что и основная структура данных TSnew.c, которая состоит из Session,
Он состоит из SessionCluster (в TSnew.c) или ServerDesc (CPnew.c и SPnew.c).
Среди них Session — это данные, относящиеся к каждому клиенту, а SessionCluster (или ServerDesc) — это информация о каждой службе, которая имеет указатель на каждый сеанс, связанный с этой службой.
Эта структура данных не выделяется динамически при наличии запроса клиента, но выделяется при первоначальной инициализации. Когда приходит новый запрос клиента, сервер ищет эти предварительно выделенные сеансы и обнаруживает, что есть несколько простаивающих. Затем используйте. и сообщить об ошибке, если простоя нет.
Самая большая разница для TS и CP(SP) заключается в том, что TS использует протокол UDP, а CP и SP используют протокол TCP. Разница между ними заключается в следующем:
1) Для клиентов протокола TCP, поскольку каждый клиент использует свой сокет, после выбора вам нужно только проверить, установлен ли fd_set каждого клиента. Для клиентов UDP вам нужно найти соответствующий процесс поиска. некоторые меры по снижению накладных расходов, вызванных поиском.
2) В протоколе TCP отправляемые данные имеют вид потока, поэтому сообщение необходимо разделить на блоки. Возможно, что за одно чтение читаются два сообщения, или сообщение может потребоваться прочитать много раз. Необходимо учитывать обе ситуации. Поэтому каждая сессия имеет buf, rstart и rlen, которые используются для хранения прочитанных, но еще не обработанных сообщений.
Аналогично, в процессе записи также необходимо учитывать, что запись может не завершиться за один раз, поэтому также необходимо сохранять wbuf, wstart и wlen в каждой сессии. В протоколе UDP это отличается. При реализации предполагается, что все содержащиеся в UDP-пакете сообщения являются полными, поэтому эти элементы не включаются.
SessionCluster (или ServerDesc) описывает сервис, состоящий из нескольких основных частей:
1) носок: описывает используемый сокет
2) cur: количество текущих клиентов
3) max: максимальное количество клиентов, которое можно разместить.
4) head: глава сеанса, head[0] — первый сеанс, head[max-1] — последний сеанс.
5) init: операция инициализации, которую необходимо выполнить каждому сеансу в этой службе (указатель функции).
6) процесс: функция обработки сообщений в этом сервисе.
7) закрытие: деструктор, необходимый в этом сервисе.
3. Описание основной структуры
process_child: основная функция, эта функция в основном используется для установки носков и wsocks. Для SP и CP wsocks устанавливается только при значении Session>0;
выбирать;
Для каждого ServerDesc (или SessionCluster) Process_type
В SP и CP для поддержки операции PUSHLIST перед каждым циклом необходимо выполнять процессJob.
В CP periodCheck также выполняется периодически для очистки просроченных соединений в TS, а periodLog выполняется периодически для очистки просроченных клиентских соединений.
тип_процесса:
Для каждого сеанса проверьте, доступен ли он для чтения. Если он доступен для чтения, проверьте, есть ли полное сообщение.
*(unsigned int *)(rbuf+rstart) <= rlen
Вызовите соответствующий процесс до тех пор, пока не будет получено полное сообщение, чтобы проверить, доступно ли оно для записи. Если оно доступно для записи и wlen>0, напишите.
4. Другие важные модули
1) Модуль конфигурации Модуль конфигурации в основном состоит из структуры NamVal, read_config, free_config. В структуре NamVal
Имя — это имя в файле cfg, ptr — указатель на хранилище, а тип — тип данных. В настоящее время поддерживаются следующие типы.
d: целочисленный тип, ptr — целочисленный указатель.
s: строковый тип, ptr — указатель на указатель, (char**)
b: тип строкового буфера, ptr — это символ *, при использовании этого типа следует обратить внимание на тип s,
read_config выделит память (malloc) для val, но для типа b ptr должен указывать на выделенную память.
Две важные функции:
read_config, параметрами являются имя файла, структура NamVal * и количество элементов структуры NamVal.
free_config, параметры те же struct NamVal* и количество элементов, что и read_config
2) модуль MySQL
Модуль mysql в основном состоит из MYSQL *local_mysql и трех функций. Эти три функции:
init_mysql, инициализирует mysql, возвращает MYSQL *, обычно используется для инициализации local_mysql
query_mysql, выполнить оператор mysql, формат query_mysql (local_mysql, «оператор mysql,
Формат такой же, как и у printf, например удалить из %s и т. д.», необходимое значение)
query_mysql_select выполняет оператор выбора MySQL. В отличие от приведенного выше, он возвращает.
MYSQL_RES *.
3) Модуль сетевой сортировки в основном состоит из сетевой структуры, функции readNETBLOCK, функции getnetwork, функции CompareNet, среди которых:
readNETBLOCK используется для чтения файла конфигурации сети и инициализации глобальной переменной NETBLOCKS.
Массив структуры сетей с элементами MAX_NET.
getnetowrk используется для поиска сетевого блока, ближайшего к IP-адресу.
CompareNet — это функция, используемая в qsort для сортировки найденных NPPeers так, чтобы NPPeers в одной сети занимали первое место.
4) Управление графом. В текущих CP, SP и NP CP может одновременно подключаться к нескольким каналам, а NP также может иметь несколько ресурсов. Для описания этой структуры введено понятие графа (каждое ребро). ) хранится указатель на NP, указатель на канал,
В TS также необходимо хранить каждый Интервал этой Сеанса в этом Канале. Каждый Канал проходит Edge.
Следующий элемент вставляется в связанный список. Головой этого связанного списка является PeerHead в структуре канала и каждого сеанса.
Следующий элемент в Edge также связан со связанным списком, а заголовком этого связанного списка является заголовок в структуре сеанса.
Связанные функции:
newEdge: добавьте новый край, параметры — Channel *, Session *. Для TS ChannelInfo необходим для инициализации информации в Edge.
delEdge: удалить ребро, параметр Edge *
5) Канальный модуль
Основными функциями модуля «Канал» являются:
TS используется для обработки NEED_PEERS, SP также необходимо для сохранения и поиска данных канала, а управление каналами осуществляется с помощью графовых структур.
Поиск каналов использует Hash по соображениям эффективности. ChannelHash использует строки.
хэш, как показано в hash_str.
Канал в TS относительно прост. Канал в SP и CP также должен управлять данными, связанными с каналом. Эти данные хранятся в каталоге /var/tmp/ на жестком диске в виде файлов. Имена файлов генерируются случайным образом. Для каждой части соответствующей информации
Сохраненные BlockData, firstsampl, message_size, message_id и offset в BlockData сохраняют информацию о первой выборке, длину блока, идентификатор блока и смещение в файле соответственно.
Обработка SP и CP различна. Для CP блоки хранятся в хэш-режиме. Например, идентификатор блока равен 1000, а.
max_queue равен 100, тогда место хранения равно 1000%100=0. Для SP, если ресурсом является канал, отправленный CS,
Это циклическая очередь, и каждый блок сохраняется в соответствующей позиции по порядку. Если он достигает конца очереди, он начинается с заголовка очереди. Если ресурсом является файл, информация BlockData не сохраняется. а исходный файл находится непосредственно по идентификатору блока.
Существует множество функций, связанных с Channel, например,locate_by_id,locate_order_by_id,newChannel,
freeChannel, saveBlock и т. д.
6) Модуль Berkeley DB задействован только в SP. Он в основном открывает файлы DB и запрашивает расположение определенного md5. В основном задействуется DB* MediaDB,
Две функции openDB и openMedia
openDB: параметр — это имя файла БД.
openMedia: параметры — md5 и целочисленный указатель, возвращают FILE * и длину файла в целочисленном указателе.
7) Модуль заданий
Модуль Job используется в CP и SP для обработки PUSHLIST. Сообщение PUSHLIST может сбросить список заданий.
Вы также можете добавить или удалить задание. Для этого используются функции в файле job.c и структура JobDes. Сеанс * и канал * в структуре JobDes используются для идентификации сеанса и канала, которому принадлежит задание, и num представляет количество BlockID, которые необходимо загрузить, job — это указатель на целое число, маска также является указателем на целое число.
job[i] — это BlockID, который необходимо загрузить. Если маска[i] равна 0, ее необходимо загрузить. Если она равна 1, она не требуется.
addJob: при добавлении задания он не проверяет, есть ли оно уже в списке, а напрямую генерирует задание и добавляет его в связанный список.
deleteJob: при удалении задания проверьте все задания в списке заданий на наличие заданий с одинаковым сеансом и каналом.
Затем установите соответствующую маску идентификатора блока, который необходимо удалить, равным 1.
processJob: для каждого задания, начиная с cur, используйтеprocess_P2P_REQUEST_real для передачи первого блока с маской 0. Если все они равны 1, удалите задание.
freeJob: удалить JobDes.
freeJobList: удалить все JobDes сеанса, обычно используется при выходе из сеанса.
8) Интервальный модуль
Модуль Interval используется в TS для представления всех быстрых интервалов на NP. В настоящее время интервал блока идентифицируется полем начала и полем длины. Основными операциями для Interval являются слияние и удаление, слияние.
Он объединяет исходный интервал и новый список интервалов, а удаление удаляет новый из исходного.
слияние: Алгоритм следующий: используется буферный список интервалов tmp.
если (старый[i] <новый[j]) tmp[k] = старый[i];
еще tmp[k] = новый[j];
Затем посмотрите, что из старого и нового можно объединить с помощью tmp[k]
удалить: сложнее, рассмотрите следующие ситуации
Начало старого[i] больше конца нового[j]
Конец старого[i] предшествует началу нового[j]
old[i] и new[j] имеют общие части, и
старый[i] содержится в новом[j]
new[j] входит в старый[i] и не включает друг друга, новый[j] входит в предыдущий и не включает друг друга, а старый[i] входит в предыдущий.
5. Несколько быстрых алгоритмов
1) В TS, использующем UDP, при первом входе клиента необходимо найти незанятую сессию. Кроме того, клиент может повторно отправлять сообщения LOGIN. В этом случае необходимо проверить, есть ли клиент. уже в списке сеансов. В-третьих, когда клиент отправляет сообщение, ему необходимо найти соответствующий сеанс.
Чтобы избежать этих запросов, соответственно используются следующие методы.
Сначала создайте хэш-таблицу. В начале все свободные сеансы связаны с Hash[0]. Каждый раз, когда приходит новый клиент, сеанс извлекается из Hash[0] и связывается с соответствующим хэшем. значение, полученное с помощью хеша, не может быть равно 0. Если оно равно 0, возвращается максимально возможный хэш.
При запросе сеанса на основе исходного порта и IP-адреса также используется эта хэш-таблица.
Когда клиент отправляет сообщение, он использует первые 3 байта из 7 байтов, используемых для проверки, и использует эти 3 байта для идентификации сеанса.
индекс, что позволяет избежать накладных расходов на запрос.
2) Используйте maxid, чтобы уменьшить количество поисков.
Хэш не используется в TCP. Элемент maxid используется для записи самого большого идентификатора в сеансе с начала сеанса.
Во время инициализации выполняется поиск незанятого сеанса с наименьшим идентификатором, поэтому сеанс можно считать относительно компактным.
Поскольку SP и CP поддерживают гораздо меньше клиентов, чем TS, такой подход приемлем.
Когда клиент выходит, может потребоваться обновить maxid. Это обновление завершается Clientclosure.
Clientclosure обновляет maxid, а затем вызывает соответствующий деструктор.
3) Обработка тайм-аута длительно простаивающих соединений. Поскольку обработка тайм-аута требует обхода всего списка, в целях экономии системных ресурсов.
IDLE занимает много времени. Кроме того, системную статистику обычно необходимо предоставлять регулярно, поэтому требуется ее своевременность.
Обычно periodLog или periodCheck определяют, какая из двух операций должна быть выполнена.
4) При запросе CPPeer, учитывая, что в настоящее время поддерживается только GCP, напрямую используется GCPCHOICE, устанавливается на GCP с наименьшей текущей нагрузкой и обновляется, когда GCP сообщает или GCP входит в систему и выходит из нее.
6. Обработка сообщений
1) Обработка сообщений TS
NP2TS_LOGIN: NP входит в систему TS и хэширует в соответствии с исходным IP-адресом и сообщенным npport. Если время с момента последней отправки сообщения NP2TS_LOGIN меньше SILENCE_TIME, он возвращается напрямую, в противном случае отправляется сообщение WELCOME.
NP2TS_REPORT: информация об интервале отчета, если обновление установлено, она будет сброшена. В противном случае она будет сначала добавлена, а затем удалена.
NP2TS_NEED_PEERS: запросить информацию об узлах, использовать findCPPeer, чтобы найти подходящий CP, использовать findNPeers.
Поиск подходящего NP. При поиске NP после обнаружения результатов они сортируются по сетям, чтобы гарантировать, что те, кто находится в одной сети, будут ранжироваться первым.
NP2TS_LOGOUT: Выход
NP2TS_RES_LIST: отправьте все РЕСУРСЫ текущего NP, используйте addSession для обработки, если этого края еще не существует, добавьте его.
NP2TS_REQ_RES: добавьте RES и верните узлы.
NP2TS_DEL_RES: удалить RES
CP2TS_REGISTER: вход в систему, CP входит в систему TS, хэширует в соответствии с исходным IP-адресом и сообщенным npport,
Если с момента последней отправки CP2TS_REGISTER прошло ILENCE_TIME, вернитесь напрямую, в противном случае отправьте
ПРИВЕТСТВЕННОЕ сообщение.
CP2TS_UPDATE: Сообщить о загрузке CP
CP2TS_NEED_PEERS: используется для запроса ECP, еще не используется.
2) Обработка сообщений SP
P2P_HELLO: Присоединяйтесь к каналу,
Если канал существует, если это медиа-файл: верните SPUPDATE, указав минимальный и максимальный идентификатор блока этого канала.
В противном случае: если этот канал закончился, верните информацию о завершении. Если канал не существует, если это медиа-файл: верните SPUPDATE, указывая минимальный и максимальный идентификатор блока этого канала, создайте канал. В противном случае: верните SPUPDATE в. указать ошибку.
P2P_PUSHLIST: сброс, добавление или удаление списка задач. При сбросе сначала удалите все связанные задачи, а затем добавьте или удалите.
CS2SP_REGISTER: Создать канал
CS2SP_UPDATE: обновить информацию о канале.
CS2SP_BLOCK: отправить блок данных.
3) Обработка сообщений CP
P2P_HELLO: присоединитесь к каналу и установите соответствующее соединение на основе предоставленного SP-адреса.
P2P_PUSHLIST: сброс или добавление и удаление списка задач.
P2P_SPUPDATE: SPUPDATE, отправленный SP, если это медиа-файл, не будет перенаправлен в NP.
P2P_RESPONSE: блок данных, отправленный SP.
Кроме того, CP также необходимо зарегистрироваться в TS.
В настоящее время используется только один тип GCP.
Расширять