Une question sur les sockets

Dans le chapitre 11 de "Advanced MAC OS Programming" , Dalrymple et Hillegass propose le code C suivant comme simpleServeur d'un socket :

<br />int main( void ) { <br /><br />	/***&nbsp; SOCKET () ****/	<br />	// int socket(int domain, int type, int protocol);	<br />	// domain = AF_INET for &quot;internetwork : UDP,TCP,...&quot;&nbsp; <br />	// type=SOCK_STREAM ==&gt; provides sequenced, reliable, two-way connection based byte streams. <br />	// protocol=0&nbsp; La liste des protocoles est dans /etc/protocols<br />	int socketfd=socket(AF_INET,SOCK_STREAM,0);&nbsp; // fd pour file descriptor<br />	// l&#39;entier socketfd est un descripteur de fichiers , il se ferme avec close()<br />	if(socketfd==-1) {perror(&quot;do not create socket&quot;);exit(EXIT_SUCCESS);}	<br />	int yes=1;<br />	if(setsockopt(socketfd,SOL_SOCKET,SO_REUSEADDR,&amp;yes,sizeof(int))==-1){<br />		perror(&quot;do not set options to socket&quot;);<br />		exit(EXIT_SUCCESS);<br />	}	<br />	<br />	/***&nbsp; BIND () ****/	<br />	// paramétrer le socket<br />	struct sockaddr_in address;<br />	address.sin_len=sizeof(struct sockaddr_in);<br />	address.sin_family=AF_INET;<br />#define PORT_NUMBER 2342<br />	address.sin_port=htons(PORT_NUMBER);<br />	address.sin_addr.s_addr=htonl(INADDR_ANY);<br />	memset(address.sin_zero,0,sizeof(address.sin_zero));<br /><br />	// int	bind(int socket, const struct sockaddr * address, socklen_t address_len);<br />	if(bind(socketfd,(const struct sockaddr *)&amp;address,sizeof(struct sockaddr_in))==-1) {<br />		perror(&quot;bind&quot;);exit(0);<br />	}<br /><br />	/***&nbsp; LISTEN () ****/<br />	// int listen(int socket, int backlog);<br />	//		The backlog parameter defines the maximum length for the queue of pending connections<br />	if(listen(socketfd,4)&lt;0) {perror(&quot;can&#39;t listen &quot;);exit(0);};<br />	<br />	<br />		<br />	/***&nbsp; ACCEPT () ****/<br />	// int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);<br />	while(1) {<br />		struct sockaddr_in new_address;<br />		char buffer[1024];<br />		int addressLength;<br />		int newSocketfd=accept(socketfd,(struct sockaddr *)&amp;new_address,&amp;addressLength);	<br />		printf(&quot;Accepting connection&#092;n&quot;);<br />		while(1) {		<br />			int result=read(newSocketfd,buffer,1024);<br />			if(result==0) {&nbsp; // End Of File<br />				break;<br />			} else if(result==-1) { // ne peut pas lire<br />				perror(&quot;read&quot;);<br />				exit(0);<br />			} else {<br />				buffer[result]=&#39;&#092;0&#39;;<br />				puts(&quot;receive : &quot;);<br />				puts(buffer);<br />			}			<br />		}<br />		close(newSocketfd);<br />	}<br /><br />	<br />	close(socketfd);<br />	return 0;<br />}<br />


Il propose ensuite d'essayer avec TELNET , ce qui donne toujours en suivant le livre
% telnet 10.0.1.142 2342
et qui est sensé établir la connexion . Mais (Gustav) malheur, j'obtiens :

<br />	% telnet 10.0.1.142 2342<br />	Trying 10.0.1.142...<br />	telnet: connect to address 10.0.1.142: Operation timed out<br />	telnet: Unable to connect to remote host<br />	%<br />


L'exécution de mon code serveur arrive sur accept(...) sans jamais recevoir de signal.
Le port 2342 non autorisé ? Comment choisit-il ce port 2342 ?

[move] :o :o ALL I NEED IS HELP  :o :o [/move]




Réponses

  • AliGatorAliGator Membre, Modérateur
    05:15 modifié #2
    Il a mis 2342 de façon arbitraire, le principal étant de se connecter sur le port sur lequel ton serveur écoute. Comme il a mis 2342 dans le code serveur (#define PORT_NUMBER), il faut que tu t'y connectes avec ce port dans la commande telnet en effet.
    Pour les ports réservés, seuls les ports inférieurs à  1024 sont réservés par le système (root). Donc pour tes propres programmes il faut mieux choisir un port >1024.

    Maintenant, tu peux essayer de voir si en te connectant sur le port 9737 à  la place. C'est la valeur de 2342 telle qu'interprétée si jamais on confond little endian et big endian (0x2609 au lieu de 0x0926). Comme le réseau utilise une endianness normalisée (je ne sais jamais laquelle mais bon) qui peut être différent de l'endianness du host... Normalement c'est justement à  ça que servent les méthodes htons et ntohs (convert from "Host TO Network, a Short-int" et convert "Network TO Host, a Short-Int") mais bon, c'est vite fait de s'emmêler les pinceaux là  dedans, alors bon ça vaut le coup de tenter.
  • Philippe49Philippe49 Membre
    septembre 2009 modifié #3
    Merci Ali pour ces précisions. Je n'avais pas pensé à  tester le big/little endian, mais ce n'est pas cela.
    Bon j'ai trouvé, avec 127.0.0.1 pour adresse IP de la machine locale cela fonctionne. D'où sortent-ils leur 10.0.1.142, un changement de convention ? Pourtant le livre est assez récent : Janvier 2006.
  • Philippe49Philippe49 Membre
    septembre 2009 modifié #4
    En plus, ces deux petits farceurs indiquent de presser ctrl-] pour obtenir le prompt de telnet pour fermer la session, alors qu'en réalité c'est ctrl $ :)  :p :p   (à  décharge, il est exact que ctrl $ écrit ^] )
    Cela ne retire rien à  la qualité de ce livre qui est à  recommander à  tous ceux qui ont envie de plonger un peu ... clair et riche.
  • AliGatorAliGator Membre, Modérateur
    05:15 modifié #5
    Pour ctrl-], je pense que c'est à  cause du QWERTY, les crochets étant, de mémoire, sur les touches ^ et $ pour respectivement [ et ] en clavier QWERTY... d'où le ctrl+] en QWERTY correspondant aux touches ctrl+$ en AZERTY... Enfin ce n'est qu'une supposition.

    Sinon, ah ben oui j'ai pensé au port, pourquoi je n'ai pas pensé à  l'IP ? :P
    En effet évidemment il faut mettre comme IP l'IP du mac auquel tu veux te connecter, celui sur lequel tourne ton serveur. Si c'est le même que celui sur lequel tu exécutes ton telnet, tu peux mettre une IP publique ou tu peux mettre en effet 127.0.0.1.
    Si tu fais ton telnet depuis un autre ordi que l'ordi sur lequel tu as lancé ton petit serveur... Bah il faut mettre l'IP de ton ordi serveur, du coup ça ne sera pas 127.0.0.1 (=localhost), ça sera l'IP locale de ton mac avec ton serveur... IP qui ressemblera à  un truc comme 10.0.1.142 ou 10.0.0.x ou 192.168.0.x très certainement... mais ils peuvent pas le deviner dans le bouquin, donc à  toi de voir l'IP que possède le mac en question.
    Enfin bon si tu fais ton test directement en local, c'est à  dire que ton client (celui qui se connecte, en l'occurrence telnet) et ton serveur (celui que tu as programmé à  l'aide du bouquin) sont sur la même machine... "localhost" ou "127.0.0.1" (qui sont synonymes) fonctionnera parfaitement.
    A part que pédagogiquement, mélanger client et serveur sur la même machine c'est p'tet pas une bonne idée car ça n'aide pas à  séparer ces deux concepts, et on comprend et identifie en général mieux qui est client et qui est serveur quand ces rôles sont joués par des ordinateurs distincts. Mais bon.
Connectez-vous ou Inscrivez-vous pour répondre.