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 10/11/2016, à 14:11

DonutMan75

[RESOLU] [C] Socket, cas d'école

Bonjour,
j'aimerais créer deux programmes client/serveur en C qui communiquerait en local via une socket.

Voici le début de mon code côté client :

   

struct sockaddr_in myaddress;

	bzero(&myaddress, sizeof(myaddress));
	myaddress.sin_family = AF_INET;
	myaddress.sin_port = htons(21054); // Port quelconque
	myaddress.sin_addr.s_addr = INADDR_LOOPBACK; // Localhost
	
	
	// STEP 1 - CREATION DE LA SOCKET
	printf("[CLIENT] Creation of sending socket...\n");

	if ((mysocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))<0)
		perror("Socket");
	
	// STEP 2 - BIND AVEC LE COUPLE (IP, PORT)
	printf("[CLIENT] Binding of the sending socket...\n");

	if (bind(mysocket, (struct sockaddr *) &myaddress, sizeof(myaddress))<0)
		perror("Bind");

Ca compile bien mais quand j'exécute, j'obtiens :

>> ./client 
[CLIENT] Creation of sending socket...
[CLIENT] Binding of the sending socket...
Bind: Cannot assign requested address

Sur le net, je lis que l'explication est que je n'utilise pas une "interface locale" mais je ne comprends pas ce que ça veut dire...
Avez-vous des idées ?

Merci d'avance

Dernière modification par DonutMan75 (Le 27/11/2016, à 08:34)

Hors ligne

#2 Le 12/11/2016, à 13:19

Bigcake

Re : [RESOLU] [C] Socket, cas d'école

Bonjour,

Coté client tu ne doit pas faire de bind(), c'est uniquement coté serveur, je pense que tu a ce problème car ton serveur est déjà 'bind' au port, 2 applications ne peuvent avoir un bind actif sur le même port dans la même période de temps.

globalement le serveur doit faire dans l'ordre :
- socket()
- bind()
- listen()
ensuite, le client doit faire :
- getaddrinfo() (si besoin)
- socket()
- connect()


"Les gens" ne sont pas cons, ils ont été habitués à la facilité et à la désinformation. Le meilleur moyen de ne pas les aider, c'est de se moquer. Le meilleur moyen de les aider, c'est de les informer, encore et encore. La réflexion viendra. N'oubliez pas que vous aussi, vous êtes le con d'un autre.
Smartphone+GNU/Linux=Librem5

Hors ligne

#3 Le 14/11/2016, à 10:00

DonutMan75

Re : [RESOLU] [C] Socket, cas d'école

Bonjour Bigcake,
merci pour ta réponse, je vais tester ça smile

D.

Hors ligne

#4 Le 17/11/2016, à 17:41

DonutMan75

Re : [RESOLU] [C] Socket, cas d'école

Bonsoir à tous,
en cherchant un peu j'ai réussi à me dépatouiller.

Tout d'abord le bind() me paraît nécessaire à la fois côté client et serveur.

Côté serveur, on indique à bind() le couple (INADDR_ANY, PORTS) pour spécifier qu'on écoute à partir de n'importe quelle interface sur le port PORTS. N'importe quelle interface signifie ici qu'on pourra joindre notre serveur aussi bien depuis la même machine (donc via l'interface LOOPBACK, classiquement en 127.0.0.1) que depuis une autre machine (par exemple 192.168.0.2 qui contacte 192.168.0.1 sur lequel tourne notre serveur)

Côté client, on indique à bind() le couple (INADDR_ANY, PORTC) pour spécifier que les messages seront envoyés via le port client PORTC (qui est généralement différent du port serveur).

Dans mon code, tout s'est résolu (par magie ??) lorsque j'ai remplacé "INADDR_LOOPBACK" par "INADDR_ANY" sans que je sache trop bien pourquoi.... Pour le moment je n'ai pas encore de réponse là dessus, je continue à creuser smile

Bonne soirée à tous smile

D.

Hors ligne

#5 Le 17/11/2016, à 19:24

eiger

Re : [RESOLU] [C] Socket, cas d'école

Salut,

Le bind() côté client n'est en général pas nécessaire. Cela peut être le cas si tu veux forcer l'utilisation d'un port source particulier (même si en général, on laisse la pile de protocoles choisir le port source). Le bind() côté client peut  également être utile si tu disposes de plusieurs interfaces réseau et que tu souhaites forcer celle que tu va utiliser pour émettre ta requête.

En revanche concernant ton histoire de INADDR_LOOPBACK / INADDR_ANY, il te manque a priori simplement un appel à htonl:

myaddress.sin_addr.s_addr = INADDR_LOOPBACK; // Localhost

devient

myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // Localhost

INADDR_ANY étant "0.0.0.0", l'oubli de htonl n'a pas d'influence.
En revanche avec INADDR_LOOPBACK, en oubliant le htonl, tu essaies de faire un bind sur l'adresse 1.0.0.127, ce qui ne marche évidemment pas.

Hors ligne

#6 Le 27/11/2016, à 08:34

DonutMan75

Re : [RESOLU] [C] Socket, cas d'école

Bonjour eiger,
merci beaucoup pour cette réponse (et désolé pour ma réponse tardive) !
Si je comprends bien les conversions vers la représentation "reseau" concerne donc aussi bien les IP et que les ports donc ?

Je peux passer le fil à resolu grâce à vous tous.

Bon dimanche !

D.

Hors ligne