Salut a tous.
je tente de realiser un systeme client / serveur, et mon systeme est presque fini, cependant j'ai segfault sur ma fermeture de socket client qui me laisse perplexe.
alors j'expose mon probleme :
j'ai un serveur qui fait un listen sur un socket (sock_in). Quand il recoit une demande de connection, il l'accept et crée le socket sock_out pour le traitement de la connection.
de son cote le socket client (sock_cli) est crée et se connecte à ce serveur et mon probleme survient quand je tente de fermer la socket sock_cli.
J'ai donc farfouiller pour essailller de comprendre et je me suis appercu que le sock_cli reprend la valeur du socket d'ecoute du serveur sock_in. (!). Et la je me dis que c'est normal que il y ait un segfault.
Comment cela est ce possible ? Y'a t il une methode pour y remedier ?
je suis a votre disposition pour vous montrer le code source, mais comme il est quand meme assez long je ne le ferais que si c'est necessaire...
en tout cas merci pour votre probable aide ...
# socket serveur / client
Posté par -=[ silmaril ]=- (site web personnel) . Évalué à 3.
Pas très clair comme message ...
Est ce que tu veut dire que la valeur de sock_cli est la meme que la valeur
de sock_in ? C'est bien cela ?
Dans ce cas je te rassure cela ne veut dire qu'une seule chose: l'ordre de
creation de tes sockets dans le client et dans le serveur est le meme.
Je parierai meme que cette valeur est 3, non ?
Quand a ton probleme.
1 qui fait le segfault ? (le client ou le serveur ?)
2 si c'est le serveur que ce passe t'il si tu utilise telnet en client ?
Sinon effectivement sans le code on ne pourra gere t'aider. (utilise pastebin ou dl.free.fr)
[^] # Re: socket serveur / client
Posté par str00mff . Évalué à 2.
1 ) c'est le client qui fait un segfault
2 ) le client telnet se connecte bien au serveur ...
Peut tu me detailler un peu plus ce que tu appelles l'ordre de creation de mes sockets dans le client et le serveur ?
[^] # Re: socket serveur / client
Posté par -=[ silmaril ]=- (site web personnel) . Évalué à 1.
Tout les processus ont par default 3 fd d'ouvert (0, 1 et 2) correspondant a stdin,stdout,et stderr. Si tu n'ouvre pas de fichier avant d'ouvrir ta
socket (ou que tu les fermes avant) le fd de la socket sera le numero 3,
si tu en ouvre une autre / un fichier il aura le numero 4 etc...
Ces 'fd' sont des indexes sur une table au niveau kernel, donc l'ordre d'ouverture conditionne la valeur du fd.
Bon sinon pour ton outils tu doit avoir oublié qque chose. As tu passé ton client au debugueur ?
Que fait tu pour fermer ta socket ?
[^] # Re: socket serveur / client
Posté par str00mff . Évalué à 2.
>Tout les processus ont par default 3 fd d'ouvert (0, 1 et 2) correspondant a stdin,stdout,et stderr. Si tu n'ouvre pas de fichier avant d'ouvrir ta
socket (ou que tu les fermes avant) le fd de la socket sera le numero 3,
>si tu en ouvre une autre / un fichier il aura le numero 4 etc...
donc si je comprend bien, deux processus peuvent avoir ouvert un meme numero de socket sans pour autant, que du point de vue du systeme, ils utilisent la meme socket ... c'est bien ca ? Donc l'hypothese que j'avais émise au début n'est plus valable (cad : le client essaie de fermer le socket du serveur, donc segfault).
je n'ai pas encore utilisé le debugger, mais ca ne va pas tarder. En fait je bosse sur d'autres problemes pour le moment...
Pour fermer ma socket, j'utilise la meme fonction pour le client et le serveur (j'ai fait une librairie multi systeme pour les socket avec les fonction de base, dont close(...) ). Pour le serveur la fonction en question ne me sort aucun segfault et se comporte tres bien, du coté client elle plante lamentablement.... ;)
Pour le moment je suis la .
[^] # Re: socket serveur / client
Posté par gc (site web personnel) . Évalué à 2.
normalement "planter" correspond à un appel mémoire incorrect (le kernel détruit ton processus car il a tenté d'accéder à un espace mémoire auquel il n'a pas accès). c'est rare que ce soit le cas avec les syscalls et impossible avec close(2). es-tu sûr que c'est sur l'appel de close ? si tu lances ton client à travers strace tu devrais voir quel est le dernier syscall avant le plantage, ça pourrat aider. si c'est un appel mémoire incorrect, lancer ton client à travers valgrind pourrait aussi grandement aider en indiquant des infos utiles de localisation du problème.
[^] # Re: socket serveur / client
Posté par str00mff . Évalué à 2.
une fois ca tombe sur le close, une autre ca tombe un peu avant.
je vais suivre tes conseils (strace et valgrind) pour avoir plus de precision...
[^] # Re: socket serveur / client
Posté par str00mff . Évalué à 2.
le retour de strace :
write(1, "+ 2006/05/24 17:02:10 Request st"..., 41+ 2006/05/24 17:02:10 Request state : 5.
) = 41
close(3) = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
[^] # Re: socket serveur / client
Posté par str00mff . Évalué à 2.
vex x86->IR: unhandled instruction bytes: 0x6 0x4D 0x3F 0x95
==15702==
==15702== Process terminating with default action of signal 11 (SIGSEGV)
==15702== Bad permissions for mapped region at address 0x8058CB5
==15702== at 0x4015920: ???
bon c'est clair que ce n'est pas le socket qui plante, mais plutot le retour de la fonction...
Si vous avez d'autre idees n'hesitez pas ...
[^] # Re: socket serveur / client
Posté par tuxyl . Évalué à 1.
# unix, udp, tcp
Posté par goeb . Évalué à 2.
Quand le serveur accepte une connexion, je ne pense pas que ce soit la peine de créer une nouvelle socket. Il peut utiliser celle qu'il vient d'accepter...
[^] # Re: unix, udp, tcp
Posté par str00mff . Évalué à 2.
pour le accept : impossible, le serveur doit etre capable de gerer des connexions simultanées...
[^] # Re: unix, udp, tcp
Posté par gc (site web personnel) . Évalué à 3.
tu te trompes. après le succès de accept(2), tu utilises la valeur de retour comme moyen de communication avec le client qui vient de se connecter, et tu peux faire un autre accept(2) pour accepter une deuxième connexion en parallèle. pour traiter correctement en parallèle cette deuxième connexion et la communication sur la première, il te suffit de mettre tous les descripteurs nécessaires dans un fd_set à passer à select(2).
voici un code minimaliste illustrant ça :
-=-=---=-=---=-=---=-=---=-=---=-=---=-=--
struct sockaddr_in client_addr;
struct timeval tv;
while (1) {
int fd;
int retval;
fd_set conns_set;
FD_ZERO(&conns_set);
/* ... ajout des descripteurs des connexions ouvertes à conns_set ... */
// ajout du descripteur correspondant à notre serveur
FD_SET(tcp_server_socket, &conns_set);
tv.tv_sec = 30;
tv.tv_usec = 0;
// attente d'une entrée/sortie sur un des descripteurs de conns_set
if ((retval = select(FD_SETSIZE, &conns_set, NULL, NULL, &tv)) == -1) {
perror("select");
exit(-1);
}
// si select est sorti sur un timeout, rien à traiter, on boucle directement
if (!retval)
continue;
/* ... traitement de l'input sur les descripteurs des connexions ouvertes s'ils sont toujours dans conns_set ... */
// traitement d'une nouvelle connexion
if (FD_ISSET(tcp_server_socket, &conns_set)) {
if ((fd = accept(tcp_server_socket, (struct sockaddr *) &client_addr, (socklen_t *) &len)) == -1) {
perror("accept");
exit(-1);
}
/* ... ajouter "fd" dans la liste des descripteurs de connexions ouvertes ... */
}
}
-=-=---=-=---=-=---=-=---=-=---=-=---=-=--
[^] # Re: unix, udp, tcp
Posté par str00mff . Évalué à 2.
Je me sert effectivement du fd renvoyé par accept et je le balance dans un fd_set...
>"il l'accept et crée le socket sock_out pour le traitement de la connection."
effectivement je me suis plutot mal exprimée. La creation de la nouvelle chaussette se fait avec le accept...
en fait ... tu viens grosso modo de me redonner le code que j'ai ecrit ;)
# MERCI :)
Posté par str00mff . Évalué à 2.
j'ai reussi a trouver mon segfault (il se cachait avec des malloc mal foutu et des retours de fonctions mal faites ;). Un petit exercice qui ma remit les idees en place :)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.