Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 21/11/2009, à 17:55

Ph3nix_

[Bash]: Backpipe + netcat: Creation d'un client-serveur

Plop all,

Voila j'essaye de creer un client serveur avec netcat (nc):

Je dois donc traiter les requêtes d'un éventuel client, pour cela j'ai trouvé une solution: Il faut lire un socket et en même temps réécrire sur ce socket pour répondre au client avec une file fifo ...


mkfifo "$TMP/$PIPE"
nc $OPT $PORT < "$TMP/$PIPE" | /bin/bash "$TMP/$TMP_SH" 1> "$TMP/$PIPE"

( nc $OPT $PORT == nc -l -p 12345 )

J'explique un peu:
- stdout est lu par /bin/bash "$TMP/$TMP_SH" (c'est un script en bash):
    * Selon ce que le script lis il va écrire soit sur stdout (&1)
    * soit sur stderr (&2)
- ensuite stdout va être redirigé dans le backpipe "$TMP/$PIPE"
- stderr va s'afficher sur le terminal coté serveur

- Dés qu'il y a écriture dans le backpipe, celui ci se dépile sur stdin, stdin qui sera redirigé vers le socket client

Si vous avez suivi, il y'a un soucis:
Je souhaiterai administrer mon serveur, et je souhaiterai que des requêtes soient traités coté serveur (et pas seulement coté client)
Ce qui n'est pas le cas avec ce code.

Ensuite:
Comment éviter que un CTRL+C coté client kill le netcat qui écoute le port ....
J'ai éssayé avec des traps ect ect... impossible

Dernière modification par Ph3nix_ (Le 21/11/2009, à 18:05)


Hiroshima 45 / Chernobyl 86 / Windows '95

Hors ligne

#2 Le 21/11/2009, à 21:03

Ph3nix_

Re : [Bash]: Backpipe + netcat: Creation d'un client-serveur

Personne ? sad


Hiroshima 45 / Chernobyl 86 / Windows '95

Hors ligne

#3 Le 22/11/2009, à 16:32

Totor

Re : [Bash]: Backpipe + netcat: Creation d'un client-serveur

Bonjour,

Je pense que ta logique n'est pas la bonne. Tu n'as pas besoin de pipe nommé car nc est justement là pour ça.

Le plus imple pour toi serait d'avoir, côté serveur, 2 modules d'écoute :
- l'un pour l'administration
- l'autre pour les demandes client

La différenciation entre les 2 s'effectue par l'utilisation de 2 ports différents.
Les 2 modules s'exécutant en parallèle.
Bien sûr, tu peux utiliser qu'un seul module d'écoute (donc un seul port) mais les demandes envoyées par les clients devront stipuler s'il s'agit de l'administration ou non. Il est tout de même préférable d'utiliser 2 modules.

Voilà à quoi pourrait ressembler ton serveur :

#!/bin/bash
export portAdm=9000
export portClient=10000

trap stopSrv SIGKILL SIGINT SIGTERM SIGSTOP

stopSrv()
{
  { nc -c "echo FIN" localhost ${portAdm}; 
     nc -c "echo FIN" localhost ${portClient} ; } 2>/dev/null
  echo "FIN !"
  # autres traitements de fin de programme
  exit 0
}

ecouteAdministrative()
{
   while true
   do
      DDESRV="$(nc -l -p ${portAdm})"
      [ "${DDESRV}" = "FIN" ] && break;
      # traitement de "DDESRV"
      echo "SRV : ${DDESRV}"
   done
}

ecouteClient()
{
   FIN=0
   while true
   do
      DDECLT="$(nc -l -p ${portClient})"
      [ "${DDECLT}" = "FIN" ] && break;
      # traitement de "DDECLT"
     echo "CLT : ${DDECLT}"
   done
}

ecouteAdministrative &
ecouteClient &
wait

Pour tester du côté du client :

# envoie d'une demande au serveur
nc -c "echo \"demande administrative\"" localhost 9000;

# envoie d'une demande au serveur
nc -c "echo \"demande client\"" localhost 10000

Côté client, il te faudra aussi un module d'écoute pour les réponses du serveur

Ce code n'est qu'une ébauche et même s'il fonctionne en l'état, il mérite d'être grandement amélioré.


-- Lucid Lynx --

Hors ligne

#4 Le 22/11/2009, à 17:46

Ph3nix_

Re : [Bash]: Backpipe + netcat: Creation d'un client-serveur

J'ai essayé ton script mais ce n'est pas une écoute interactive, ou alors j'ai mal utilisé ton script..

DDECLT="$(nc -l -p ${portClient})"
Quand tu écris ça la demande sera traité que lorsque le client aura:

soit fais une requète avec:

nc -c "echo "ma requète" localhost 9000|10000

"traitement de $DDECLT ou $DDESERV"

ou alors lorsque le client aura fais:

nc localhost 9000|1000
ma requète1
ma requète2
CTRL^C

"traitement de $DDECLT ou $DDESRV"
Le principe du backpipe c'est que les requète sont traités en temps réelle

nc localhost 9000|1000
ma requète1 [b]"traitement requète1"[/b]
ma requète2 [b]"traitement requète2"[/b]
ma requète3 [b]"traitement requète3"[/b]
CTRL^C

Je te montres un exemples d'execution de mon script:

PROMPT> nc localhost 12345
16:48:44 Serveur: Bienvenu sur le serveur racine

Serveur: Pour communiquer avec moi, essayez /CMD
/HELP
Serveur: User command:
Serveur: /HELP:       Affiche ce texte
Serveur: /NEW:        Creer un serveur fils
Serveur: /WHO:        Affiche le port du serveur courrant
Serveur: /LIST:       Affiche la liste des serveurs fils

Serveur: Root command:
Serveur: /KILLALL:    Kill tous les serveurs fils
Serveur: /KILL PORT:  Kill le serveur fils ouvert sur le port
/NEW
Serveur: Ouverture du serveur fils sur le port n° 12346
/LIST
Serveur: Port des serveurs fils en attente:
12346
/NEW
Serveur: Ouverture du serveur fils sur le port n° 12347
/LIST
Serveur: Port des serveurs fils en attente:
12346
12347
/NEW
Serveur: Ouverture du serveur fils sur le port n° 12348
/KILL 12347
Serveur: Root commande, veuillez entrer le mot de passe:
allo
Serveur: Authentification réussie
Serveur: Arret du serveur fils sur le port n° 12347
/LIST
Serveur: Port des serveurs fils en attente:
12346
12348

Ce qui s'affiche dans le terminal ou le serveur a été lancé:

Lancement du serveur racine sur le port n° 12345
Veuillez entrer le mot de passe administrateur:
allo
Veuillez confirmer le mot de passe administrateur:
allo
Mot de passe enregistré
16:48:56 Connect: 12345: nouveau client
16:48:56 Request: 12345
16:49:00 Request: 12345
16:49:09 New: 12345: creation d'un serveur fils sur le port n° 12346
16:49:09 Request: 12345
16:49:13 Request: 12345
16:49:18 New: 12345: creation d'un serveur fils sur le port n° 12347
16:49:18 Request: 12345
16:49:21 Request: 12345
16:49:23 New: 12345: creation d'un serveur fils sur le port n° 12348
16:49:23 Request: 12345
16:49:29 Quit: 12347: fin de connexion
16:49:29 Delete: 12347: erase du serveur
16:49:29 Request: 12345
16:49:40 Request: 12345
16:51:38 Quit: 12345: fin de connexion

Dernière modification par Ph3nix_ (Le 22/11/2009, à 17:52)


Hiroshima 45 / Chernobyl 86 / Windows '95

Hors ligne

#5 Le 23/11/2009, à 10:48

Totor

Re : [Bash]: Backpipe + netcat: Creation d'un client-serveur

OK, je n'avais pas vu cet aspect d'interactivité...
je regarde


-- Lucid Lynx --

Hors ligne

#6 Le 23/11/2009, à 22:47

Totor

Re : [Bash]: Backpipe + netcat: Creation d'un client-serveur

Je t'avoue que je n'ai pas cherché dans ta continuité.
J'ai donc réalisé un petit script "serveur" et un petit script "client".
Le client se connecte au serveur et ensuite demande de taper quelque chose au clavier. La saisie est envoyée au serveur.
La seule chose que fait le serveur est d'écouter les demandes client et de leur renvoyer pour affichage.

Serveur :

#!/bin/bash
export portAdm=9010
export portClient=10000

stopSrv()
{
   {
	   nc -c 'echo FIN' ${HOSTNAME} ${portAdm}
       nc -c 'echo FIN' ${HOSTNAME} ${portClient}; } 2>/dev/null
   
  echo "FIN serveur !"
  # autres traitements de fin de programme
  exit 0
}

envoiClient()
{
	CLIENT="$1"
	TEXTE="$2"
	
	CLIENT=${CLIENT/*\/}
	CLIENTHOST=${CLIENT%%:*}
	CLIENTPORT=${CLIENT#*:}
	
	nc -c "echo ${TEXTE}" "${CLIENTHOST}" "${CLIENTPORT}"
}

ecouteAdministrative()
{
  while true
  do  
      DDESRV="$(nc -l -p ${portAdm} ${HOSTNAME})"
	  [ $? -ne 0 -o "${DDESRV}" = "FIN" ]  && break;
	  echo "SRV : ${DDESRV}" >&2
      # traitement de "DDESRV"      
   done
}

ecouteClient()
{
   while true
   do
      DDECLT="$(nc -l -p  ${portClient} ${HOSTNAME})"	  
      [ $? -ne 0 -o "${DDECLT}" = "FIN" ] && break;
	  # traitement de "DDECLT"
     
	 case "${DDECLT}" in
	 CLIENT=*) 
		# Nouveau Client, on l'enregistre
		INFOS=${DDECLT/CLIENT=}
		CLIENTHOST=${INFOS%%:*}
		CLIENTPORT=${INFOS#*:}
		CLIENTID=${RANDOM}
		CLIENT="${CLIENTID}/${INFOS}"
		CLIENTS+=( "${CLIENTS}"  )
		envoiClient "${CLIENT}" "${CLIENTID}";;
	 *) 
	     envoiClient "${DDECLT%%;*}"  "\"${HOSTNAME}>${DDECLT#*;}\"";;
	 esac
   done
}

export CLIENTS
export TOTO=1
trap "stopSrv" SIGKILL SIGINT SIGTERM SIGSTOP

ecouteAdministrative &
ecouteClient &
wait

Client :

#!/bin/bash

export srvHost="<Nom machine serveur>"
export srvPort=10000
export cltHost="${HOSTNAME}"
export cltPort="9001"

trap "stopClt" SIGKILL SIGINT SIGTERM SIGSTOP

stopClt()
{
  nc -c 'echo FIN' ${cltHost} ${cltPort} 2>/dev/null
   
  echo "FIN Client !"
  # autres traitements de fin de programme
  exit 0
}

identificationAuServeur()
{
	# demande identification
	nc -c "echo CLIENT=${cltHost}:${cltPort}" "${srvHost}" "${srvPort}" >& /dev/null
	[ $? -ne 0 ] && return 1;
	# attente identifiant par le serveur
	nc -l -p "${cltPort}" "${cltHost}"
}

ecouteServeur()
{
	while true
	do
	   REPONSE="$(nc -l -p ${cltPort} ${cltHost})"
	   [ $? -ne 0 -o "${REPONSE}" = "FIN" ] && break;
	   echo -e "${REPONSE}"
	done
}

ecritureServeur()
{
	echo "Taper les instructions du serveur : "
    while read ligne
    do
      nc -c "echo \"${CltInfos};${ligne}\"" "${srvHost}" "${srvPort}"
    done
}

export IDClient=$(identificationAuServeur)
[ ! "${IDClient}" ] && { echo "Connexion serveur impossible"; exit 1; }
echo "ID Client : ${IDClient}"
export CltInfos="${IDClient}/${cltHost}:${cltPort}"
ecouteServeur & 
ecritureServeur
wait

Note : la variable srvHost est à modifier

Ces 2 scripts ne sont pas "secur". Si tu arrètes le serveur, le client ne le détecte pas et si tu arrète le client, il n'est pa déréférencé du serveur... mais bon, ce n'est pas grand chose.
Et puis, il faudrait, côté client, choisir un port aléatoirement car (je n'ai pas fait le test) si tu lances 2 clients sur la même machine, je ne sais pas comment ça va réagir. Ou alors, il faut interdire l'utilisation de 2 clients sur la même machine mais ce n'est franchement pas top !
De même, il faudrait tester qu'il n'y a pas déjà un serveur de lancer !


-- Lucid Lynx --

Hors ligne

#7 Le 05/06/2014, à 13:32

teunniq

Re : [Bash]: Backpipe + netcat: Creation d'un client-serveur

Salut!

5 an plus tard... il n'est pas trop tard non ?
J'ai essayé les scripts ci-dessus, mais le client n'arrive pas à se connecter au serveur.
J'ai ouvert 2 terminaux, le client /home/moi/client et le serveur /home/moi/serveur
Je pense que cela est du au fait que pour l'host du serveur j'ai saisi localhost, du coup l'host du serveur et du client sont identique... mais en même temps c'est la même machine donc je ne vois pas comment faire!

Hors ligne