1. Description de l'architecture Le protocole actuel présente les caractéristiques suivantes :
1) Le client envoie une requête au serveur et la longueur de chaque requête est variable. La longueur de la requête est spécifiée dans le premier INT.
2) Chaque serveur fournit généralement des services à plusieurs clients. Par exemple, TS doit fournir des services au CP et au NP en même temps.
CP fournit des services à NP et à d'autres CP, et est également client d'autres CP, TS et SP.
3) Lorsque chaque serveur sert un client, cela est généralement à long terme et implique plusieurs allers-retours de requêtes et de réponses.
Une telle structure est principalement conçue pour prendre en charge un grand nombre de connexions client simultanées, peu importe si des threads ou des processus sont utilisés, des services efficaces ne peuvent pas être fournis, donc select doit être utilisé.
Mode d'interrogation.
2. Description de la structure des données de base : Pour chaque client, certaines informations correspondant au client doivent être enregistrées. CPnew.c, SPnew.c actuels.
C'est fondamentalement la même chose que la structure de données de base de TSnew.c, qui se compose de Session,
Il se compose de SessionCluster (dans TSnew.c) ou de ServerDesc (CPnew.c et SPnew.c).
Parmi eux, Session correspond aux données liées à chaque client et SessionCluster (ou ServerDesc) correspond aux informations sur chaque service, qui ont un pointeur vers chaque session liée au service.
Cette structure de données n'est pas allouée dynamiquement lorsqu'il y a une demande client, mais a été allouée lors de l'initialisation initiale. Lorsqu'une nouvelle demande client arrive, le serveur recherche ces sessions pré-allouées et constate qu'il y en a des inutilisées. et signaler une erreur s'il n'y a pas de temps d'inactivité.
Pour TS et CP(SP), la plus grande différence est que TS utilise le protocole UDP, tandis que CP et SP utilisent le protocole TCP. La différence entre les deux est la suivante :
1) Pour les clients du protocole TCP, puisque chaque client utilise un socket différent, après la sélection, il vous suffit de vérifier si le fd_set de chaque client est défini. Pour les clients UDP, vous devez trouver le client correspondant qu'un processus de recherche utilise. quelques mesures pour réduire les frais généraux occasionnés par la recherche.
2) Dans le protocole TCP, les données envoyées se présentent sous la forme d'un flux, le message doit donc être divisé en blocs. Il est possible que deux messages soient lus en une seule lecture, ou qu'un message doive être lu plusieurs fois. . Les deux situations doivent être prises en compte. Par conséquent, chaque session a un buf, un rstart et un rlen, qui sont utilisés pour stocker les messages qui ont été lus mais pas encore traités.
De même, pendant le processus d'écriture, il est également nécessaire de considérer que l'écriture peut ne pas être terminée en une seule fois, il est donc également nécessaire de conserver wbuf, wstart et wlen dans chaque session. C'est différent dans le protocole UDP. Lors de la mise en œuvre, on suppose que chaque paquet UDP Les messages contenus dans sont tous complets, ces éléments ne sont donc pas inclus.
SessionCluster (ou ServerDesc) décrit un service composé de plusieurs parties principales :
1) chaussette : décrit la douille utilisée
2) cur : le nombre de clients actuels
3) max : le nombre maximum de clients pouvant être hébergés
4) head : Head of Session, head[0] est la première session, head[max-1] est la dernière session
5) init : l'opération d'initialisation qui doit être effectuée par chaque session de ce service (pointeur de fonction).
6) processus : la fonction de traitement des messages dans ce service
7) fermeture : le destructeur requis dans ce service
3. Description de la structure principale
process_child : fonction principale, cette fonction est principalement utilisée pour définir les chaussettes et les wsocks Pour SP et CP, wsocks n'est défini que lorsque wlen de Session>0 ;
sélectionner;
Pour chaque ServerDesc (ou SessionCluster), process_type
Dans SP et CP, afin de prendre en charge l'opération PUSHLIST, processJob doit être exécuté avant chaque cycle.
Dans CP, periodCheck est également effectué périodiquement pour effacer les connexions expirées dans TS, et periodLog est effectué périodiquement pour effacer les connexions client expirées.
type_processus :
Pour chaque Session, vérifiez si elle est lisible. S'il est lisible, vérifiez s'il y a un message complet,
*(entier non signé *)(rbuf+rstart) <= rlen
Appelez le processus correspondant jusqu'à ce qu'il n'y ait pas de message complet pour vérifier s'il est accessible en écriture et wlen>0, écrivez.
4. Autres modules importants
1) Module de configuration Le module de configuration se compose principalement de struct NamVal, read_config, free_config Dans la structure NamVal,
Name est le nom dans le fichier cfg, ptr est le pointeur vers le stockage et type est le type de données Actuellement, les types suivants sont pris en charge.
d : Type entier, ptr est un pointeur entier
s : type de chaîne, ptr est un pointeur vers un pointeur, (char **)
b : type de tampon de chaîne, ptr est un char *, vous devez faire attention lorsque vous utilisez ce type, pour le type s,
read_config allouera de la mémoire (malloc) pour le val, mais pour le type b, ptr doit pointer vers la mémoire allouée.
Les deux fonctions importantes sont :
read_config, les paramètres sont le nom du fichier, une struct NamVal*, et le nombre d'éléments de la struct NamVal
free_config, les paramètres sont les mêmes struct NamVal * et le nombre d'éléments que read_config
2) module mysql
Le module mysql se compose principalement de MYSQL *local_mysql et de trois fonctions. Ces trois fonctions sont.
init_mysql, initialise mysql, renvoie un MYSQL*, généralement utilisé pour initialiser local_mysql
query_mysql, exécutez une instruction mysql, le format est query_mysql (local_mysql, "instruction mysql,
Le format est le même que celui de printf, comme delete from %s, etc.", la valeur requise)
query_mysql_select, exécute une instruction mysql select Différent de ce qui précède, il renvoie un.
MYSQL_RES *.
3) Le module de tri de réseau est principalement composé de la structure des réseaux, de la fonction readNETBLOCK, de la fonction getnetwork, de la fonction compareNet, parmi lesquelles,
readNETBLOCK est utilisé pour lire le fichier de configuration réseau et initialiser la variable globale NETBLOCKS est un.
Tableau de structure de réseaux, avec des éléments MAX_NET.
getnetowrk est utilisé pour trouver le netblock le plus proche d'une adresse IP
compareNet est une fonction utilisée dans qsort pour trier les NPPeers trouvés afin que les NPPeers du même réseau soient classés en premier.
4) Gestion des graphes Dans les CP, SP et NP actuels, CP peut rejoindre plusieurs canaux en même temps, et NP peut également avoir plusieurs ressources Afin de décrire cette structure, le concept de graphe est introduit. ) est stocké Un pointeur vers NP, un pointeur vers Channel,
Dans TS, il est également nécessaire de stocker chaque intervalle de cette session dans ce canal. Chaque canal passe par Edge.
Le cnext in est enchaîné dans une liste chaînée. La tête de cette liste chaînée est le PeerHead dans la structure de canal, et chaque session.
L'enext dans Edge est également intégré dans une liste chaînée, et l'en-tête de cette liste chaînée est l'en-tête dans la structure de session.
Les fonctions associées sont :
newEdge : ajoutez un nouveau Edge, les paramètres sont Channel *, Session * Pour TS, un ChannelInfo est nécessaire pour initialiser les informations dans Edge.
delEdge : Supprime un bord, le paramètre est Edge *
5) Module de canal
Les principales fonctions du module Canal sont :
TS est utilisé pour traiter NEED_PEERS, SP doit également enregistrer et rechercher les données des canaux, et les canaux sont gérés à l'aide de structures graphiques.
La recherche de chaînes utilise Hash pour des raisons d'efficacité.
hash, comme indiqué dans hash_str.
Le canal dans TS est relativement simple. Le canal dans SP et CP doivent également gérer les données liées au canal. Ces données sont stockées dans le répertoire /var/tmp/ du disque dur sous forme de fichiers. Pour chaque information pertinente,
Enregistrés par BlockData, firstsampl, message_size, message_id et offset dans BlockData, stockent respectivement les informations sur le premier échantillon, la longueur du bloc, l'identifiant du bloc et le décalage dans le fichier.
Le traitement de SP et CP est différent Pour CP, les blocs sont stockés en mode hachage. Par exemple, l'ID de bloc est 1000, tandis que.
max_queue est 100, alors l'emplacement de stockage est 1000%100=0 Pour SP, si la ressource est un canal envoyé par CS,
Il s'agit d'une file d'attente circulaire, et chaque bloc est stocké à la position correspondante dans l'ordre. S'il atteint la fin de la file d'attente, il démarre en tête de la file d'attente. Si la ressource est un fichier, les informations BlockData ne sont pas enregistrées. et le fichier original se trouve directement en fonction du blockID.
Il existe de nombreuses fonctions impliquant Channel, telles que Locate_by_id, Locate_order_by_id, newChannel,
freeChannel, saveBlock, etc.
6) Le module Berkeley DB n'est impliqué que dans SP. Il ouvre principalement les fichiers DB et interroge l'emplacement d'un certain md5. Il implique principalement DB* MediaDB,
Les deux fonctions openDB et openMedia
openDB : Le paramètre est le nom du fichier DB
openMedia : Les paramètres sont md5 et un pointeur entier, renvoie FILE* et la longueur du fichier, dans le pointeur entier
7) Module emploi
Le module Job est utilisé dans CP et SP pour traiter PUSHLIST. Le message PUSHLIST peut réinitialiser la liste de tâches.
Vous pouvez également ajouter un travail ou supprimer un travail. Cela implique les fonctions de job.c et la structure JobDes. Une Session * et un Canal * dans la structure JobDes sont utilisés pour identifier la Session et le Canal auxquels appartient le travail. num représente le nombre de BlockID qui doivent être téléchargés, job est un pointeur vers un entier, mask est également un pointeur vers un entier,
job[i] est le BlockID qui doit être téléchargé. Si mask[i] est 0, il doit être téléchargé. S'il est 1, il n'est pas nécessaire.
addJob : lors de l'ajout d'un travail, il ne vérifie pas si le travail est déjà dans la liste, mais génère directement un travail et l'ajoute à la liste chaînée.
deleteJob : lors de la suppression d'une tâche, vérifiez toutes les tâches de la liste des tâches pour les tâches avec la même session et le même canal.
Définissez ensuite le masque correspondant du blockID qui doit être supprimé sur 1.
processJob : Pour chaque job, à partir de cur, utilisez process_P2P_REQUEST_real pour transmettre le premier bloc avec le masque 0. S'ils sont tous à 1, supprimez le job.
freeJob : Supprimer un JobDes.
freeJobList : supprime tous les JobDes d'une session, généralement utilisés à la fin de la session.
8) Module d'intervalle
Le module Intervalle est utilisé dans TS pour représenter tous les intervalles rapides sur NP. Actuellement, l'intervalle de bloc est identifié par un champ de début et un champ de longueur. Les principales opérations pour Intervalle sont la fusion et la suppression, la fusion.
Il combine l'intervalle d'origine et la nouvelle liste d'intervalles, tandis que la suppression supprime la nouvelle de la liste d'origine.
fusion : L'algorithme est le suivant, utilisant la liste d'intervalles de tampon tmp.
si (ancien[i] < nouveau[j]) tmp[k] = ancien[i];
sinon tmp[k] = nouveau[j];
Ensuite, regardez lesquels de l'ancien et du nouveau peuvent être fusionnés avec tmp[k]
delete : c'est plus compliqué, considérez les situations suivantes
Le début du vieux[i] est plus grand que la fin du nouveau[j]
La fin du vieux[i] est avant le début du nouveau[j]
old[i] et new[j] ont des parties communes, et
old[i] est contenu dans new[j]
new[j] est inclus dans old[i] et ne s'inclut pas, new[j] est inclus dans le précédent et ne s'inclut pas, et old[i] est inclus dans le précédent.
5. Quelques algorithmes rapides
1) Dans TS utilisant UDP, lorsque le client se connecte pour la première fois, il est nécessaire de trouver une session inactive. De plus, le client peut envoyer des messages LOGIN à plusieurs reprises. Dans ce cas, il est nécessaire de vérifier si le client est. déjà dans la liste des sessions. Troisièmement, lorsque le client envoie un message, il doit trouver la session correspondante.
Afin d'éviter ces requêtes, les méthodes suivantes sont utilisées respectivement.
Tout d'abord, créez une table de hachage. Au début, toutes les sessions libres sont liées à Hash[0]. Chaque fois qu'un nouveau client arrive, la session est retirée de Hash[0] et liée au hashid correspondant. la valeur obtenue par hachage ne peut pas être 0. Si elle est 0, le plus grand hashid possible est renvoyé.
L'interrogation de la session en fonction du port source et de l'adresse IP utilise également cette table de hachage.
Lorsque le client envoie un message, il utilise les 3 premiers octets des 7 octets utilisés pour la vérification, et utilise ces 3 octets pour identifier la Session.
indice, évitant ainsi la surcharge des requêtes.
2) Utilisez maxid pour réduire le nombre de recherches.
Le hachage n'est pas utilisé dans TCP. L'élément maxid est utilisé pour enregistrer le plus grand identifiant de la session depuis.
Lors de l'initialisation, la session inactive avec le plus petit ID est recherchée, de sorte que la session peut être considérée comme relativement compacte.
Étant donné que SP et CP prennent en charge beaucoup moins de clients que TS, ce traitement est acceptable.
Lorsque le client quitte, il peut être nécessaire de mettre à jour le maxid. Cette mise à jour est effectuée par Clientclosure.
Clientclosure met à jour maxid puis appelle le destructeur correspondant.
3) Traitement du délai d'attente des connexions inactives à long terme Étant donné que le traitement du délai d'attente nécessite de parcourir la liste entière, afin d'économiser les ressources du système,
IDLE prend beaucoup de temps. De plus, les statistiques du système doivent généralement être rapportées régulièrement, c'est pourquoi la rapidité est requise.
Généralement, periodLog ou periodCheck déterminent laquelle des deux opérations doit être effectuée.
4) Lors de l'interrogation de CPPeer, étant donné qu'actuellement seul GCP est pris en charge, GCPCHOICE est directement utilisé, défini sur GCP avec la charge actuelle la plus faible et mis à jour lorsque GCP signale ou que GCP se connecte et se déconnecte.
6. Traitement des messages
1) Traitement des messages TS
NP2TS_LOGIN : NP se connecte à TS et hache en fonction de l'adresse IP source et du npport signalé. Si le temps écoulé depuis la dernière fois que le message NP2TS_LOGIN a été envoyé est inférieur à SILENCE_TIME, il est renvoyé directement, sinon un message de BIENVENUE est envoyé.
NP2TS_REPORT : informations sur l'intervalle de rapport. Si l'actualisation est vraie, elle sera réinitialisée. Sinon, elle sera d'abord ajoutée puis supprimée.
NP2TS_NEED_PEERS : interrogez les informations sur les homologues, utilisez findCPPeer pour trouver un CP approprié, utilisez findNPPeers
Recherchez un NP approprié Lors de la recherche de NP, après avoir trouvé les résultats, ils sont triés par réseaux pour garantir que ceux du même réseau sont classés en premier.
NP2TS_LOGOUT : Quitter
NP2TS_RES_LIST : Envoyez toutes les RESSOURCES du NP actuel, utilisez addSession pour le traitement, si ce bord n'existe pas encore, ajoutez-le
NP2TS_REQ_RES : ajoutez RES et renvoyez les pairs
NP2TS_DEL_RES : Supprimer RES
CP2TS_REGISTER : connexion, CP se connecte à TS, hache en fonction de l'adresse IP source et du npport signalé,
Si ILENCE_TIME s'est écoulé depuis le dernier envoi de CP2TS_REGISTER, retournez directement, sinon envoyez
Message de BIENVENUE.
CP2TS_UPDATE : rapporter la charge du CP
CP2TS_NEED_PEERS : utilisé pour la requête ECP, pas encore utilisé
2) Traitement des messages SP
P2P_HELLO : Rejoignez une chaîne,
Si le canal existe, s'il s'agit d'un fichier Media : Renvoie SPUPDATE, en indiquant le blockID minimum et maximum de ce canal
Sinon : Si ce canal est terminé, renvoyez l'information de fin. Si le canal n'existe pas, s'il s'agit d'un fichier Media : Renvoyez un SPUPDATE en indiquant le blockID minimum et maximum de ce canal, créez le canal. Sinon : Renvoyez un SPUPDATE à. indiquer une erreur.
P2P_PUSHLIST : Réinitialiser ou ajouter ou supprimer la liste des tâches Lors de la réinitialisation, supprimez d'abord toutes les tâches associées, puis ajoutez ou supprimez.
CS2SP_REGISTER : Créer un canal
CS2SP_UPDATE : mettre à jour les informations sur la chaîne
CS2SP_BLOCK : envoyer un bloc de données
3) Traitement des messages CP
P2P_HELLO : rejoignez un canal et établissez une connexion correspondante en fonction de l'adresse SP fournie
P2P_PUSHLIST : Réinitialiser ou ajouter et supprimer la liste des tâches
P2P_SPUPDATE : SPUPDATE envoyé par SP, s'il s'agit d'un fichier Media, ne sera pas transmis à NP
P2P_RESPONSE : Bloc de données envoyé par le SP.
De plus, le CP doit également s'inscrire auprès du TS.
Actuellement, un seul type de GCP est utilisé.
Développer