Problème SDL_Net

a marqué ce sujet comme résolu.

Bonjour, je suis nouveau sur ce site (dont, à première vue, les cours sont très intéressants :D ) et j’ai un problème: je suis en train de programmer un petit jeu en réseau (en C avec SDL), mais je rencontre un problème: la réception des données avec SDLNet_TCP_Recv();

(La partie du programme qui pose problème, je précise qu’elle n’est pas dans une boucle.)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
char chaine[NBTILEX*NBTILEY+1];
   IPaddress ip;
   TCPsocket tcpserveur;

   int result;

   if(SDLNet_Init() != 0) {
       fprintf(stderr, "Erreur d'initialisation de SDL_Net\n");
       return EXIT_FAILURE;
   }
   if(SDLNet_ResolveHost(&ip,"127.0.0.1",5790) != 0) {
       fprintf(stderr,"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
       return EXIT_FAILURE;
   }

   tcpserveur = SDLNet_TCP_Open(&ip);
   if(tcpserveur == NULL)
   {
       fprintf(stderr,"Erreur de connection à l'ip: %s",SDLNet_GetError());
       return EXIT_FAILURE;
   }


   FILE *fichier = NULL;
   fichier = fopen("niveau.lvl","r+");

       SDLNet_TCP_Recv(tcpserveur, chaine, strlen(chaine));
       fprintf(fichier,"%s", chaine);
       SDLNet_TCP_Send(tcpserveur, chaine, strlen(chaine));

Pour faire des tests, j’utilise comme serveur un petit programme en Perl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
use Socket;
use strict;

my $port = shift || 5790; # port
my $proto = getprotobyname('tcp'); # protocole
my $serveur = "localhost"; # adresse IP du serveur (ici localhost)

socket(SOCKET, PF_INET, SOCK_STREAM, $proto) or die "Echec de creation du serveur: $! \n"; # cree le socket
setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1) or die "Can't set socket option to SO_REUSEADDR $!\n"; # options du socket

bind(SOCKET, pack_sockaddr_in($port, inet_aton($serveur))) or die "Erreur bind au port $port \n"; # attribue le socket a l'IP et au port
listen (SOCKET, 1) or die "Listen: $!"; # ecoute les connexion pour savoir si un client se connecte

print "Serveur lance sur le port: $port \n";

my $client_addr;
my $line;

while ($client_addr = accept(NEW_SOCKET, SOCKET))
{
my $nameClient = gethostbyaddr($client_addr, AF_INET);
print "Connexion recue par: $nameClient \n";

my $message = <>;
chomp $message;
send(SOCKET, "$message", 0);
recv(NEW_SOCKET, $line, 2000 , 0);
print("$line \n");


close NEW_SOCKET or die "erreur de fermeture du client \n"; #on ferme la connexion
print ("Connection termine \n");
close SOCKET  or die "Erreur de fermeture du socket: $! \n";
print "Socket ferme \n";
}

`

Mais la réception ne semble pas se faire (je n’obtiens rien dans le fichier "niveau.lvl" en envoyant "333333333" avec le sevreur par exemple) et l’accusé de réception (SDLNet_TCP_Send();) n’est pas reçu par le serveur…

J’aimerai donc bien savoir où sont mes erreurs.

Merci :D

+0 -0

Salut,

Le mieux, c’est de voir un petit peu ce qui passe effectivement à l’aide de netstat et de tcpdump. Tout d’abord, quand tu démarres ton script Perl, est-ce que la commande netstat -t -n -a te montre bien qu’un service écoute sur le port 5970 avec comme adresse 127.0.0.1 ? Si oui, lance alors la commande tcpdump comme suit et exécute ensuite ton programme C.

1
$ tcpdump -n -X -i lo port 5970
+1 -0

Merci pour ta réponse. Je retrouve effectivement mon serveur avec netstat. Dans le Tcpdump, je vois effectivement le "33333333333333333333333333" envoyé par le serveur, mais rien du côté du jeu (il envoie un paquet vide), ni dans "niveau.lvl"

+0 -0
1
2
3
4
5
6
7
8
 Flags [P.], seq 1:29, ack 1, win 342, options [nop,nop,TS val 319263 ecr 318235], length 28
    0x0000:  4500 0050 7521 4000 4006 c784 7f00 0001  E..Pu!@.@.......
    0x0010:  7f00 0001 169e a3b0 f1df ae3a 9124 f528  ...........:.$.(
    0x0020:  8018 0156 fe44 0000 0101 080a 0004 df1f  ...V.D..........
    0x0030:  0004 db1b 3333 3333 3333 3333 3333 3333  ....333333333333
    0x0040:  3333 3333 3333 3333 3333 3333 3333 200a  33333333333333..

`

et l’accusé de réception:

1
2
3
4
5
6
7
Flags [.], ack 29, win 342, options [nop,nop,TS val 319263 ecr 319263], length 0
    0x0000:  4500 0034 2e3e 4000 4006 0e84 7f00 0001  E..4.>@.@.......
    0x0010:  7f00 0001 a3b0 169e 9124 f528 f1df ae56  .........$.(...V
    0x0020:  8010 0156 fe28 0000 0101 080a 0004 df1f  ...V.(..........
    0x0030:  0004 df1f                                ....

`

Ah ! Effectivement je me suis trompé, en remplacant SOCKET par NEW_SOCKET j’ai l’accusé de réception (mais seulement 16 caractères max bizarrement) et des choses dans le fichier ! Mais le Tile Mapping ne se fait pas (sauf si j’enlève le "fprintf"). Et j’ai un "segmentation fault: core dumped" quand j’arrête le jeu.

+0 -0

la trame complète en envoyant 55555555555555 avec le serveur:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
22:41:03.936167 IP 127.0.0.1.5790 > 127.0.0.1.60056: Flags [P.], seq 3778350700:3778350716, ack 1575651946, win 342, options [nop,nop,TS val 1459070 ecr 1456838], length 16
    0x0000:  4500 0044 34aa 4000 4006 0808 7f00 0001  E..D4.@.@.......
    0x0010:  7f00 0001 169e ea98 e135 0e6c 5dea 8a6a  .........5.l]..j
    0x0020:  8018 0156 fe38 0000 0101 080a 0016 437e  ...V.8........C~
    0x0030:  0016 3ac6 3535 3535 3535 3535 3535 3535  ..:.555555555555
    0x0040:  3535 200a                                55..
22:41:03.936193 IP 127.0.0.1.60056 > 127.0.0.1.5790: Flags [.], ack 16, win 342, options [nop,nop,TS val 1459070 ecr 1459070], length 0
    0x0000:  4500 0034 b0b1 4000 4006 8c10 7f00 0001  E..4..@.@.......
    0x0010:  7f00 0001 ea98 169e 5dea 8a6a e135 0e7c  ........]..j.5.|
    0x0020:  8010 0156 fe28 0000 0101 080a 0016 437e  ...V.(........C~
    0x0030:  0016 437e                                ..C~
22:41:03.936221 IP 127.0.0.1.60056 > 127.0.0.1.5790: Flags [P.], seq 1:17, ack 16, win 342, options [nop,nop,TS val 1459070 ecr 1459070], length 16
    0x0000:  4500 0044 b0b2 4000 4006 8bff 7f00 0001  E..D..@.@.......
    0x0010:  7f00 0001 ea98 169e 5dea 8a6a e135 0e7c  ........]..j.5.|
    0x0020:  8018 0156 fe38 0000 0101 080a 0016 437e  ...V.8........C~
    0x0030:  0016 437e 3535 3535 3535 3535 3535 3535  ..C~555555555555
    0x0040:  3535 200a                                55..
22:41:03.936233 IP 127.0.0.1.5790 > 127.0.0.1.60056: Flags [.], ack 17, win 342, options [nop,nop,TS val 1459070 ecr 1459070], length 0
    0x0000:  4500 0034 34ab 4000 4006 0817 7f00 0001  E..44.@.@.......
    0x0010:  7f00 0001 169e ea98 e135 0e7c 5dea 8a7a  .........5.|]..z
    0x0020:  8010 0156 fe28 0000 0101 080a 0016 437e  ...V.(........C~
    0x0030:  0016 437e                                ..C~
22:41:03.975839 IP 127.0.0.1.60056 > 127.0.0.1.5790: Flags [.], ack 17, win 342, options [nop,nop,TS val 1459080 ecr 1459070], length 0
    0x0000:  4500 0034 b0b3 4000 4006 8c0e 7f00 0001  E..4..@.@.......
    0x0010:  7f00 0001 ea98 169e 5dea 8a7a e135 0e7d  ........]..z.5.}
    0x0020:  8010 0156 fe28 0000 0101 080a 0016 4388  ...V.(........C.
    0x0030:  0016 437e                                ..C~
22:41:07.863283 IP 127.0.0.1.60056 > 127.0.0.1.5790: Flags [F.], seq 17, ack 17, win 342, options [nop,nop,TS val 1460051 ecr 1459070], length 0
    0x0000:  4500 0034 b0b4 4000 4006 8c0d 7f00 0001  E..4..@.@.......
    0x0010:  7f00 0001 ea98 169e 5dea 8a7a e135 0e7d  ........]..z.5.}
    0x0020:  8011 0156 fe28 0000 0101 080a 0016 4753  ...V.(........GS
    0x0030:  0016 437e                                ..C~
22:41:07.863294 IP 127.0.0.1.5790 > 127.0.0.1.60056: Flags [.], ack 18, win 342, options [nop,nop,TS val 1460051 ecr 1460051], length 0
    0x0000:  4500 0034 f513 4000 4006 47ae 7f00 0001  E..4..@.@.G.....
    0x0010:  7f00 0001 169e ea98 e135 0e7d 5dea 8a7b  .........5.}]..{
    0x0020:  8010 0156 0f43 0000 0101 080a 0016 4753  ...V.C........GS
    0x0030:  0016 4753                                ..GS

`
+0 -0

Ah ! Effectivement je me suis trompé, en remplacant SOCKET par NEW_SOCKET j’ai l’accusé de réception (mais seulement 16 caractères max bizarrement) et des choses dans le fichier ! Mais le Tile Mapping ne se fait pas (sauf si j’enlève le "fprintf"). Et j’ai un "segmentation fault: core dumped" quand j’arrête le jeu.

S01den

Là, c’est un autre problème. ;)

+0 -0

Je ne vois toujours pas pourquoi je n’ai que 16 caractères qui me sont renvoyés; d’ailleurs, si j’envoie un nombre de caractère supérieur ou égal à 20 je n’obtient tout simplement rien dans le fichier, ni l’accusé de réception; sinon, entre 17 et 19 caractères, je n’ai que 16 caractères qui me sont renvoyés, et rien de nouveau dans le fichier texte… De plus si je n’envoie qu’un seul caractère, j’ai apparemment une suite de "s" envoyés avec le caractères:

1
2
3
4
5
6
18:48:08.653668 IP 127.0.0.1.38752 > 127.0.0.1.5790: Flags [P.], seq 1:17, ack 4, win 342, options [nop,nop,TS val 507690 ecr 507690], length 16
    0x0000:  4500 0044 b433 4000 4006 887e 7f00 0001  E..D.3@.@..~....
    0x0010:  7f00 0001 9760 169e 0452 08dc dd99 772c  .....`...R....w,
    0x0020:  8018 0156 fe38 0000 0101 080a 0007 bf2a  ...V.8.........*
    0x0030:  0007 bf2a 3320 0a73 7373 7373 7373 7373  ...*3..sssssssss
    0x0040:  7373 7373  
+0 -0

Je veux dire et si tu écris plutôt ceci, qu’est-ce que cela te donne ?

1
2
3
4
if (SDLNet_TCP_Recv(tcpserveur, chaine, NBTILEX * NBTILEY + 1) <= 0) {
    fprintf(stderr,"Erreur lors de la réception : %s\n", SDLNet_GetError());
    return EXIT_FAILURE;
}
+0 -0

Mmm… Dans ce cas, changeons de méthode : laisse tomber ton petit serveur écrit en Perl pour l’instant et lance la commande suivante.

1
$ nc -v -l 127.0.0.1 5790

Celle-ci est bloquante et attend donc une connexion sur le port 5790. Ensuite, démarre ton application cliente et écrit dans la console du serveur (donc de la commande nc) le message qui doit être envoyé au client, puis voit ce que le client répond. Peux-tu m’en donner la sortie ?

PS : toujours en employant le code C corrigé, bien entendu.

+0 -0

Bon, je te prie de m’excuser, mais on aurait dû commencer par là tout de suite : pour détecter l’erreur, il serait bon de récupérer la valeur de SDLNet_TCP_Recv et vérifier ensuite si le nombre de bytes envoyer correspond à celle-ci. En bref, le code suivant fonctionne-t-il chez toi avec nc et le script Perl ?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <stdlib.h>

#include <SDL/SDL_net.h>


int
main(void)
{
    char buf[255];
    IPaddress ip;
    TCPsocket tcpserveur;
    int n;

    if (SDLNet_Init() != 0) {
        fprintf(stderr, "Erreur d'initialisation de SDL_Net\n");
        return EXIT_FAILURE;
    }
    if (SDLNet_ResolveHost(&ip, "127.0.0.1", 5790) != 0) {
        fprintf(stderr,"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
        return EXIT_FAILURE;
    }

    tcpserveur = SDLNet_TCP_Open(&ip);

    if (tcpserveur == NULL) {
        fprintf(stderr,"Erreur de connection à l'ip: %s", SDLNet_GetError());
        return EXIT_FAILURE;
    }
    if ((n = SDLNet_TCP_Recv(tcpserveur, buf, sizeof buf - 1)) <= 0) {
        fprintf(stderr,"Erreur lors de la réception : %s\n", SDLNet_GetError());
        return EXIT_FAILURE;
    } 

    buf[n] = 0;
    printf("buf: %s\n", buf);

    if (SDLNet_TCP_Send(tcpserveur, buf, n) < n) {
        fprintf(stderr,"Erreur lors de l'envoi : %s\n", SDLNet_GetError());
        return EXIT_FAILURE;
    }

    return 0;
}

De mon côté, c’est bon.

1
2
3
4
$ nc -v -l 127.0.0.1 5790 
Connection from localhost 42914 received!
333333333333333333333333333333
333333333333333333333333333333
+0 -0

Re, j’ai encore un problème ( le dernier espérons :D ). Sur mon serveur, j’envoie le contenu de "niveau.lvl" quand je détruis un bloc (quand la map est modifiée quoi), donc sur mon client je dois surveiller si je reçois des données ou non; donc je fais:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
        serverSocketActivity = SDLNet_SocketReady(tcpserveur);
        if(serverSocketActivity != 0)
        {
        if ((n = SDLNet_TCP_Recv(tcpserveur, chaine, sizeof chaine - 1)) <= 0) {
            fprintf(stderr,"Erreur lors de la réception : %s\n", SDLNet_GetError());
        return EXIT_FAILURE;
        }

        chaine[n] = 0;
        rewind(fichier);
        fputs(chaine,fichier);
        }

dans ma boucle principale, mais cela ne fonctionne pas… (Et oui, les données du serveur sont bien envoyées quand je détruis un bloc, j’ai testé avec nc :) )

+0 -0

Oui, mais ça ne fonctionne pas. (Pire encore, le client se ferme lorqu’il doit envoyer les données, mais uniquement avec le serveur que j’ai programmé, avec netcat il n’y a pas de problème et les bonnes données sont envoyées)

Le code du serveur:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
        ready = SDLNet_CheckSockets(socketset,10);

        if(ready==-1) {
            printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError());
            fprintf(stderr,"SDLNet_CheckSockets: %s\n", SDLNet_GetError());
        }
        else if(ready)
        {
            if(SDLNet_SocketReady(tcpserveur)) {
                if ((n = SDLNet_TCP_Recv(tcpserveur, chaine, sizeof chaine))<=0) {
                    fprintf(stderr,"Erreur lors de la réception : %s\n", SDLNet_GetError());
                    return EXIT_FAILURE;
                }
                else
                {
                fichier = fopen("niveau.lvl","w+");
                chaine[n] = 0;
                fputs(chaine,fichier);
                fclose(fichier);
                }
            }
        }
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte