Écoutez plusieurs ports d'un serveur
Est-il possible de lier et de les écouter plusieurs ports dans Linux dans une application?
source d'informationauteur user2175831
Vous devez vous connecter pour publier un commentaire.
Est-il possible de lier et de les écouter plusieurs ports dans Linux dans une application?
source d'informationauteur user2175831
Vous devez vous connecter pour publier un commentaire.
Pour chaque port que vous voulez écouter, vous:
socket
.bind
.listen
sur le socket de sorte qu'il est mis en place avec une écoute de la file d'attente.À ce point, votre programme est à l'écoute sur de multiples supports. Pour accepter les connexions sur ces prises, vous avez besoin de savoir qui socket un client se connecte. C'est là que
select
. Il se trouve que j'ai un code qui fait exactement ce assis autour, voici donc une complète testé exemple de l'attente pour les connexions sur des prises multiples et retour le descripteur de fichier de connexion. L'adresse distante est retourné dans d'autres paramètres (le tampon doit être fourni par l'appelant, tout comme l'accepter).(
socket_type
ici est un typedef pourint
sur les systèmes Linux, etINVALID_SOCKET
est-1
. Ceux qui sont là parce que ce code a été porté sous Windows.)Ce code n'indique pas à l'appelant de port du client connecté, mais vous pouvez facilement ajouter un
int *
paramètre qui permettrait d'obtenir le descripteur de fichier qui a vu la connexion entrante.Vous ne
bind()
à un seul socket, puislisten()
etaccept()
-- la prise pour le bind est pour le serveur, le fd de laaccept()
est pour le client. Vous faites vos sélectionner sur la dernière recherche pour un client une prise de données dans l'attente de l'entrée.Dans une telle situation, vous pouvez être intéressé par libevent. Il va faire le travail de l'
select()
pour vous, probablement à l'aide d'une bien meilleure interface commeepoll()
.L'énorme inconvénient avec
select()
est l'utilisation de laFD_...
macros qui limite le nombre de sockets pour le nombre maximum de bits dans lefd_set
variable (de l'ordre de 100 à 256). Si vous avez un petit serveur avec 2 ou 3 connexions, vous serez amende. Si vous avez l'intention de travailler un beaucoup plus grand serveur, puis lefd_set
pourrait facilement obtenir survolées.Aussi, l'utilisation de la
select()
oupoll()
vous permet d'éviter les threads du serveur (c'est à dire que vous pouvezpoll()
votre prise et savoir si vous pouvezaccept()
read()
ouwrite()
.)Mais si vous voulez vraiment faire Unix, alors vous pouvez aussi envisager de
fork()
-ing avant d'appeleraccept()
. Dans ce cas, vous n'avez pas absolument besoin de laselect()
oupoll()
(sauf si vous êtes à l'écoute sur plusieurs ip/ports et voulons que tous les enfants soient capables de répondre à toutes les connexions entrantes, mais vous avez inconvénients avec... le noyau peut vous envoyer une autre demande, alors que vous êtes déjà en cours de traitement d'une demande, alors que, avec juste unaccept()
le noyau sait que vous êtes occupé, si ce n'est dans leaccept()
appeler lui-même—bien, il ne fonctionne pas exactement comme cela, mais en tant qu'utilisateur, c'est la façon dont cela fonctionne pour vous.)Avec le
fork()
vous préparez le support dans le processus principal et ensuite appelerhandle_request()
dans un processus enfant d'appeler leaccept()
fonction. De cette façon, vous pouvez avoir n'importe quel nombre de ports et d'un ou plusieurs enfants à écouter sur chaque. C'est la meilleure façon de vraiment très rapidement répondre à toute connexion entrante sous Linux (c'est à dire en tant qu'utilisateur et aussi longtemps que vous avez les processus enfants d'attente pour un client, il est instantanée.)Noter que le
handle_request()
fonction est montré ici que le traitement d'une demande. L'avantage de la manipulation d'une seule demande est que vous pouvez le faire de la manière Unix: allouer les ressources nécessaires et une fois que la demande est exaucée,exit(0)
. Leexit(0)
fera appel à la nécessaireclose()
free()
etc. pour vous.En revanche, si vous souhaitez gérer plusieurs demandes en ligne, vous voulez vous assurer que les ressources seront libérées avant de revenir en
accept()
appel. Aussi, lesbrk()
fonction est à peu près jamais être appelé à réduire l'empreinte mémoire de votre enfant. Cela signifie qu'il a tendance à augmenter un peu chaque maintenant et puis. C'est pourquoi un serveur comme Apache 2 est configuré pour répondre à un certain nombre de demandes par enfant avant de commencer un nouvel enfant (par défaut, c'est entre 100 et 1 000 ces jours-ci.)