IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Problème de connexion sockets Windows


Sujet :

C

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2020
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2020
    Messages : 4
    Points : 1
    Points
    1
    Par défaut Problème de connexion sockets Windows
    Bonjour a tous!

    J'ai un petit souci avec mes sockets Windows. Lorsque j'ouvre mes ports orange, que je mets les bonnes IP (ip du pc sur le serveur et ip publique sur le client), que je lance le serveur et que je me connecte avec le client, le client reçoit bien un message ("quel est votre nom et votre age"), mais le serveur quant à lui, ne reçoit aucune donnée de la part du client (mais m'affiche bien que le client s'est connecté). J'ai essayé le même programme avec l'ipv4 de mon pc sur les deux .c et testé avec mon ordi et un autre (sur la même co) et ça fonctionne très bien. (Et sans l'autorisation du port, le client ne se connecte pas du tout donc ça m'étonnerait que le problème vienne de l'ouverture de port). J'ai aussi essayé de désactiver intégralement mon antivirus et désactiver les pare-feu orange (choisir le niveau de sécurité: faible) sans succès.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    //serveur
    #include<windows.h>
    #include<unistd.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include <pthread.h>
     
     
    typedef struct User
    {
        char nom[30];
        int age;
    }User;
     
    void *function(void *arg)
    {
        int socket = *(int*)arg;
        char msg[] = "quel est votre nom et votre age";
        User user;
        send(socket, msg, strlen(msg)+1, 0);
        recv(socket, &user, sizeof(user), 0);
        printf("le client s'appelle %s et a %d ans\n", user.nom, user.age);
        close(socket);
        free(arg);
        pthread_exit(NULL);
    }
     
    int main(void)
    {
        setbuf(stdout, NULL);
        setbuf(stderr, NULL);
     
        WSADATA WSAData;
        if(WSAStartup(MAKEWORD(2, 0), &WSAData))
        {
           printf("WSA n'a pas pu être initialisé.\n");
        }
     
        int socketServer = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in addrServer;
        memset(&addrServer, 0, sizeof (addrServer));
        addrServer.sin_addr.s_addr = inet_addr("192.168.1.38");
        addrServer.sin_family = AF_INET;
        addrServer.sin_port = htons(30000);
     
        bind(socketServer, (const struct sockaddr *)&addrServer, sizeof(addrServer));
        printf("bind: %d\n", socketServer);
     
        listen(socketServer,4);
        printf("listen\n");
     
        pthread_t threads[4];
     
        for(int i=0; i<4; i++)
        {
            struct sockaddr_in addrClient;
            socklen_t csize = sizeof(addrClient);
            int socketClient = accept(socketServer, (struct sockaddr *)&addrClient, &csize);
            printf("accept\n");
            printf("client: %d\n", socketClient);
     
            int *arg = malloc(sizeof(int));
            *arg = socketClient;
            pthread_create(&threads[i], NULL, function, arg);
        }
     
     
        for(int i=0; i<4; i++)
        {
            pthread_join(threads[i], NULL);
        }
     
     
        close(socketServer);
        printf("Close\n");
     
        WSACleanup();
        return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    //client
    #include<windows.h>
    #include<unistd.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include <pthread.h>
     
    typedef struct User
    {
        char nom[30];
        int age;
    } User;
     
    int main(void)
    {
        setbuf(stdout, NULL);
        setbuf(stderr, NULL);
     
        WSADATA WSAData;
        if(WSAStartup(MAKEWORD(2, 0), &WSAData))
        {
            printf("WSA n'a pas pu être initialisé.\n");
        }
     
        int socketClient = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in addrClient;
        memset(&addrClient, 0, sizeof (addrClient));
        addrClient.sin_addr.s_addr = inet_addr("90.70.0.168");
        addrClient.sin_family = AF_INET;
        addrClient.sin_port = htons(30000);
        connect(socketClient, (const struct sockaddr *)&addrClient, sizeof(addrClient));
        printf("connecte\n");
     
     
        /******action*******/
        User user;
        char msg[33];
        recv(socketClient, msg, 32, 0);
        printf("%s\n", msg);
        scanf("%s %d", user.nom, &user.age);
        send(socketClient, (void *)&user, sizeof(user), 0);
        /***************/
     
     
     
        close(socketClient);
     
        WSACleanup();
        return 0;
    }
    Quelqu'un pourrait-il m'expliquer pourquoi ça ne fonctionne pas?

    Merci à tous!

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Olocki Voir le message
    Quelqu'un pourrait-il m'expliquer pourquoi ça ne fonctionne pas?
    Je n'en ai aucune idée. Toutefois moi si j'étais confronté à ce souci, je regarderais ce que renvoient send() et recv() et éventuellement strerror(errno) (sans oublier les autres fonctions critiques comme connect() ou bind). C'est ce qu'on faisait avant qu'il y ait des forums, et donc ce n'est pas parce qu'il y a des forums qu'il faut oublier les fondamentaux...

    Citation Envoyé par Olocki Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int *arg = malloc(sizeof(int));
    *arg = socketClient;
    pthread_create(&threads[i], NULL, function, arg);
    ??????

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    pthread_create(&threads[i], NULL, function, &socketClient);
    Et bien évidemment tu supprimes le free dans la fonction.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Y'a tellement d'erreurs que c'est pas évident de tout faire tenir en un post...
    Déjà tu oublies 99% des vérifications d'erreurs.
    send n'est pas vraiment bloquant.
    recv est bloquant mais c'est plus subtil.
    accept est bloquant.
    connect est bloquant.

    Maintenant qu'on a lu les bases niveau 0 de l'API socket, que voit-on dans ton code ?
    - le serveur bind une interface spécifique et non ADDR_ANY, sûrement sans raison autre que de vouloir laisser un rateau et marcher dessus à l'occasion
    - le serveur va faire 4 boucles pour récupérer 4 clients
    - pour chaque client il lance un thread
    - pour une raison injustifiable l'argument du thread est alloué dynamiquement
    - le thread du client envoie quelque chose, puis attend de recevoir quelque chose
    > tu as de la chance que le recv bloquera assez pour que l'envoi soit fait
    - dès qu'un truc est reçu, il ferme la socket
    - et tu mets fin au thread qui se terminera de toute façon puisqu'on est à la fin de la fonction

    Quant au client
    - il se connecte
    - on prie pour que ça fonctionne
    - il reçoit des trucs
    > on a aucune idée de ce qu'il recevra réellement, mais mettons que la chance est avec nous et on reçoit bien la chaîne entière
    - il envoie un truc
    - puis il se termine
    > autant dire qu'il a extrêmement peu de chance, voire aucune, que ce qu'il espère envoyer arrive à destination
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2020
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2020
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Merci beaucoup pour vos réponses !
    Je suis sincèrement désolé de vous avoir autant frustré par mon code terriblement mauvais et je m'en excuse
    Je viens tout juste de commencer à apprendre le réseau (d'où le niveau 0 )
    J'ai revu mon code et essayé d’intégrer un maximum de vérif. (j’espère que c'est bon)

    SERVEUR:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
     
    //serveur
    #include<windows.h>
    #include<unistd.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include <pthread.h>
     
     
    typedef struct User
    {
        char nom[30];
        int age;
    }User;
     
    void *function(void *arg)
    {
        int sock_err;
        int socket = *(int*)arg;
        char msg[] = "quel est votre nom et votre age";
        User user;
        sock_err = send(socket, msg, strlen(msg)+1, 0);
     
        if(sock_err != SOCKET_ERROR)
            printf("Chaine envoyée : %s\n", msg);
        else
            printf("Erreur de transmission\n");
     
        if(recv(socket, (void *)&user, sizeof(user), 0) != SOCKET_ERROR)
        {
            printf("Message recu\n");
            printf("le client s'appelle %s et a %d ans\n", user.nom, user.age);
        }
        else
            printf("Erreur : aucun message recu\n");
     
        printf("Fermeture de la socket client\n");
        close(socket);
        pthread_exit(NULL);
        return NULL;
    }
     
    int main(void)
    {
        setbuf(stdout, NULL);
        setbuf(stderr, NULL);
     
        WSADATA WSAData;
        if(WSAStartup(MAKEWORD(2, 0), &WSAData))
        {
           printf("WSA n'a pas pu être initialisé.\n");
        }
     
        int sock_err;
        int socketServer = socket(AF_INET, SOCK_STREAM, 0);
     
        if(socketServer != INVALID_SOCKET)
        {
            struct sockaddr_in addrServer;
            memset(&addrServer, 0, sizeof (addrServer));
            addrServer.sin_addr.s_addr = inet_addr("192.168.1.38");
            addrServer.sin_family = AF_INET;
            addrServer.sin_port = htons(30000);
     
            sock_err = bind(socketServer, (const struct sockaddr *)&addrServer, sizeof(addrServer));
     
            if(sock_err != SOCKET_ERROR)
            {
                printf("bind: %d\n", socketServer);
                sock_err = listen(socketServer,4);
     
                if(sock_err != SOCKET_ERROR)
                {
                    printf("listen\n");
     
                    pthread_t threads[4];
     
                    for(int i=0; i<4; i++)
                    {
                        struct sockaddr_in addrClient;
                        socklen_t csize = sizeof(addrClient);
                        int socketClient = accept(socketServer, (struct sockaddr *)&addrClient, &csize);
                        printf("accept\n");
                        printf("client: %d\n", socketClient);
     
                        pthread_create(&threads[i], NULL, function, &socketClient);
                    }
     
     
                    for(int i=0; i<4; i++)
                        pthread_join(threads[i], NULL);
                }
                else
                    perror("listen");
            }
            else
                perror("bind");
     
            printf("Fermeture de la socket serveur\n");
            close(socketServer);
        }
        else
            perror("socket");
     
        printf("Fermeture serveur\n");
     
        WSACleanup();
        return 0;
    }
    CLIENT:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    //client
    #include<windows.h>
    #include<unistd.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include <pthread.h>
     
    typedef struct User
    {
        char nom[30];
        int age;
    } User;
     
    int main(void)
    {
        setbuf(stdout, NULL);
        setbuf(stderr, NULL);
     
        WSADATA WSAData;
        if(WSAStartup(MAKEWORD(2, 0), &WSAData))
        {
            printf("WSA n'a pas pu être initialisé.\n");
        }
     
        User user;
        char msg[33];
     
        int socketClient = socket(AF_INET, SOCK_STREAM, 0);
     
        struct sockaddr_in addrClient;
        memset(&addrClient, 0, sizeof (addrClient));
        addrClient.sin_addr.s_addr = inet_addr("90.70.0.168");
        addrClient.sin_family = AF_INET;
        addrClient.sin_port = htons(30000);
     
        if(connect(socketClient, (const struct sockaddr *)&addrClient, sizeof(addrClient)) != SOCKET_ERROR)
        {
            printf("Connexion à %s sur le port %d\n", inet_ntoa(addrClient.sin_addr), htons(addrClient.sin_port));
            if(recv(socketClient, msg, 32, 0) != SOCKET_ERROR)
                printf("%s\n", msg);
            else
                printf("Message non reçu");
     
            scanf("%s %d", user.nom, &user.age);
     
            if(send(socketClient, (void *)&user, sizeof(user), 0) != SOCKET_ERROR)
                printf("Message envoye\n");
            else
                printf("Erreur de transmission\n");
        }
        else
            printf("ERREUR DE CONNEXION\n");
     
     
        /***************/
        system("pause");
        printf("Fermeture de du client");
        close(socketClient);
        WSACleanup();
     
        return 0;
    }
    Mon code est-il plus convenable?

    Et maintenant le serveur m'affiche "Erreur : aucun message reçu" (le 2eme else dans le thread)

    Merci encore pour tous vos conseils.

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    C'est mieux et tu peux déjà le constater : tu as une erreur bien visible qui apparaît.
    Maintenant le pourquoi de l'erreur est aussi dans mon message précédent. Non le serveur ne recevra presque jamais rien puisque le client se termine avant d'avoir envoyé réellement.

    https://bousk.developpez.com/cours/r...-protocole/#LI
    l'appel à recv permet de récupérer jusque len octets de données.
    Je ne vais pas recopier ici des chapitres de mon cours, tu peux cliquer sur le lien dans ma signature et le lire.
    Les données ne sont envoyées que si le client reste connecté suffisamment longtemps pour que l'envoi soit effectif.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Olocki Voir le message
    Mon code est-il plus convenable?
    C'est pas pour nous, c'est pour toi. Quand on fait une action critique, on la vérifie. Ca permet de "vérifier" que l'action a fonctionné (évidemment c'est con comme la lune ce genre d'évidence mais c'est quand elle n'y est pas qu'on regrette).
    Ceci dit, au lieu de tester la réussite, perso je préfère teste l'échec. Ca me permet quand j'arrive au code utile de de continuer à l'écrire à gauche et donc d'avoir beaucoup de place.
    Donc au lieu de faire
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if (truc1 == ok) {
    	if (truc2 == ok) {
    		if (truc3 == ok) {
    			// ici on commence à coder utile, mais il n'y a plus de place !!!
    		}else {
    			perror("truc3");
    		}
    	} else {
    		perror("truc2");
    	}
    } else {
    	perror("truc1");
    }

    Déjà imagine dans ton code que tu doives rajouter un test sur truc0 avant truc1... obligé de tout décaler. Donc je préfère écrire
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if (truc1 != ok) {
    	perror("truc1");
    	sortie de la boucle , de la fonction
    }
    if (truc2 != ok) {
    	perror("truc2");
    	sortie de la boucle , de la fonction
    }
    if (truc3 != ok) {
    	perror("truc3");
    	sortie de la boucle , de la fonction
    }
    // Code utile - Ok, j'ai toute la place
    Je veux rajouter un test "truc0", ben je rajoute juste 3 lignes avant truc1.
    Autre chose, il n'y a pas de constante "SOCKET_ERROR" et tout ça. Une fonction standard réussit elle renvoie 0 ou un nombre positif (si en plus elle veut dire de combien elle réussit), elle ne réussit pas elle renvoie -1. Donc on cherche l'échec on cherche "-1".
    Il peut y avoir 0 qui a un statut un peu batard car lui il signifie "l'opération n'a pas planté, mais elle n'a rien fait car il n'y avait rien à faire".
    Et en plus le résultat de l'opération, si l'opération réussit, est souvent une information utile (nb d'octets envoyés, reçus, etc). Donc la variable qui récupère ce résultat ne doit pas se nommer "err". Même si on teste l'échec, on s'attend à une réussite.

    Citation Envoyé par Olocki Voir le message
    Et maintenant le serveur m'affiche "Erreur : aucun message reçu" (le 2eme else dans le thread)
    Hé ben chez-moi, ton code fonctionne !!! Hé oui !!! Bon ça ne veut pas dire qu'il est parfait, mais au-moins les sockets communiquent.

    Bon toutefois n'étant pas sous Windows, j'ai enlevé tout ce qui fait référence à cet OS (déjà les WSA, et les thread). J'ai donc repris ton code à l'identique, mais adapté à Linux

    Le serveur
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    //serveur
    #include <sys/types.h>						// Types prédéfinis "c"
    #include <sys/socket.h>						// Généralités sockets
    #include <sys/param.h>						// Paramètres et limites système
    #include <netinet/in.h>						// Spécifications socket internet
    #include <arpa/inet.h>						// Adresses format "arpanet"
    #include<unistd.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<pthread.h>
     
    typedef struct User
    {
        char nom[30];
        int age;
    }User;
     
    void *function(void *arg)
    {
        int sock_err;
        int socket = *(int*)arg;
        char msg[] = "quel est votre nom et votre age";
        User user;
        sock_err = send(socket, msg, strlen(msg)+1, 0);
     
        if(sock_err > 0)
            printf("Chaine envoyée : %s\n", msg);
        else
            printf("Erreur de transmission\n");
     
        if(recv(socket, (void *)&user, sizeof(user), 0) > 0)
        {
            printf("Message recu\n");
            printf("le client s'appelle %s et a %d ans\n", user.nom, user.age);
        }
        else
            printf("Erreur : aucun message recu\n");
     
        printf("Fermeture de la socket client\n");
        close(socket);
        pthread_exit(NULL);
        return NULL;
    }
     
    int main(void)
    {
        setbuf(stdout, NULL);
        setbuf(stderr, NULL);
     
        int sock_err;
        int socketServer = socket(AF_INET, SOCK_STREAM, 0);
     
        if(socketServer != -1)
    	{
            struct sockaddr_in addrServer;
            memset(&addrServer, 0, sizeof (addrServer));
            addrServer.sin_addr.s_addr = INADDR_ANY;
            addrServer.sin_family = AF_INET;
            addrServer.sin_port = htons(30000);
     
            sock_err = bind(socketServer, (const struct sockaddr *)&addrServer, sizeof(addrServer));
     
            if(sock_err != -1)
            {
                printf("bind: %d\n", socketServer);
                sock_err = listen(socketServer,1);
     
                if(sock_err != -1)
                {
                    printf("listen\n");
     
                    struct sockaddr_in addrClient;
                    socklen_t csize = sizeof(addrClient);
                    int socketClient = accept(socketServer, (struct sockaddr *)&addrClient, &csize);
                    printf("accept\n");
                    printf("client: %d\n", socketClient);
    				function(&socketClient);
                }
                else
                    perror("listen");
            }
            else
                perror("bind");
     
            printf("Fermeture de la socket serveur\n");
            close(socketServer);
        }
        else
            perror("socket");
     
        printf("Fermeture serveur\n");
     
        return 0;
    }

    Le client
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    //client
    #include <sys/types.h>						// Types prédéfinis "c"
    #include <sys/socket.h>						// Généralités sockets
    #include <sys/param.h>						// Paramètres et limites système
    #include <netinet/in.h>						// Spécifications socket internet
    #include <arpa/inet.h>						// Adresses format "arpanet"
    #include<unistd.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
     
     
    typedef struct User
    {
        char nom[30];
        int age;
    } User;
     
    int main(void)
    {
        setbuf(stdout, NULL);
        setbuf(stderr, NULL);
     
        User user;
        char msg[33];
     
        int socketClient = socket(AF_INET, SOCK_STREAM, 0);
     
        struct sockaddr_in addrClient;
        memset(&addrClient, 0, sizeof (addrClient));
        addrClient.sin_addr.s_addr = inet_addr("127.0.0.1");
        addrClient.sin_family = AF_INET;
        addrClient.sin_port = htons(30000);
     
        if(connect(socketClient, (const struct sockaddr *)&addrClient, sizeof(addrClient)) != -1)
        {
            printf("Connexion à %s sur le port %d\n", inet_ntoa(addrClient.sin_addr), htons(addrClient.sin_port));
            if(recv(socketClient, msg, 32, 0) > 0)
                printf("%s\n", msg);
            else
                printf("Message non reçu");
     
            scanf("%s %d", user.nom, &user.age);
     
            if(send(socketClient, (void *)&user, sizeof(user), 0) > 0)
                printf("Message envoye\n");
            else
                printf("Erreur de transmission\n");
        }
        else
            printf("ERREUR DE CONNEXION\n");
     
     
        /***************/
        system("pause");
        printf("Fermeture de du client");
        close(socketClient);
     
        return 0;
    }

    Tu remarqueras que pour le serveur j'utilise l'adresse INADDR_ANY dont avait parlé Bousk.

    Donc ce code fonctionne, donc peut-être le souci vient soit des WSA, soit des thread.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Autre chose, il n'y a pas de constante "SOCKET_ERROR" et tout ça. Une fonction standard réussit elle renvoie 0 ou un nombre positif (si en plus elle veut dire de combien elle réussit), elle ne réussit pas elle renvoie -1. Donc on cherche l'échec on cherche "-1".
    Sur Windows l'API socket retourne SOCKET_ERROR en cas d'erreur. C'est un define à -1.

    Citation Envoyé par Sve@r Voir le message
    Hé ben chez-moi, ton code fonctionne !!! Hé oui !!! Bon ça ne veut pas dire qu'il est parfait, mais au-moins les sockets communiquent.
    Il fonctionne grâce à la pause que tu as ajouté à la fin. Pause pendant laquelle les données ont le temps de transiter.

    C'est très simple : allume un tuyau d'eau, puis éteins le directement. Tu vas jamais arroser quoi que ce soit de cette façon.
    Le bug ce n'est pas le tuyau ou le robinet, c'est que l'eau n'a jamais le temps de sortir du tuyau.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Il fonctionne grâce à la pause que tu as ajouté à la fin. Pause pendant laquelle les données ont le temps de transiter.
    Oui enfin j'ai rien ajouté, la pause y était déjà. J'ai juste retiré du code d'origine les références à Windows et aux thread.

    Citation Envoyé par Bousk Voir le message
    C'est très simple : allume un tuyau d'eau, puis éteins le directement. Tu vas jamais arroser quoi que ce soit de cette façon.
    Le bug ce n'est pas le tuyau ou le robinet, c'est que l'eau n'a jamais le temps de sortir du tuyau.
    Oui je suis bien d'accord. Je n'ai pas présenté ce code comme la réussite de l'année, je l'ai juste présenté pour prouver à Olocki que le souci ne vient pas des sockets, en référence à son premier post où il parle de port à ouvrir, de firewall à désactiver, etc. Donc si ce code fonctionne chez-lui il saura qu'il n'y a pas de souci de port ou de firewall.
    J'ai déjà codé des clients/serveurs Linux pour m'exercer (via TCP, via UDP et via socket). Bien évidemment chez moi mon client ne s'arrête pas.

    Quoique... en fait si, dans le TP que j'ai créé, mon client fait saisir une chaine et l'envoie au serveur qui l'affiche. Et si la chaine est "EOT" alors il s'arrête. Toutefois le serveur reçoit quand-même "EOT" lui permettant de comprendre que son client s'est arrêté. T'es sûr que le send() ne fonctionne pas si l'emetteur s'arrête juste après ??? On est tout de même dans le monde du connecté, donc dans ce monde, quand je dis "au revoir" au téléphone, même si je raccroche un pouillième de seconde après, mon correspondant entend quand-même "au revoir"...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Je n'avais pas vu la pause dans son code. En ce cas le problème vient certainement du bind qui bind une interface spécifique.
    Oui send ne fait que mettre dans la file d'envoi des données. L'envoi réel sur le réseau va survenir, si le socket existe suffisamment longtemps pour qu'il survienne.
    En local ou LAN c'est quasi instantané, mais sur internet rien n'est moins sûr. Ça dépend de ce que ton système a déjà en attente d'envoi etc.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2020
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2020
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Merci pour tous vos conseils et informations !

    Citation Envoyé par Sve@r Voir le message
    Ceci dit, au lieu de tester la réussite, perso je préfère teste l'échec.
    C'est vrai que c'est plus propre, je ferai comme ça maintenant !

    Citation Envoyé par Sve@r Voir le message
    Donc ce code fonctionne, donc peut-être le souci vient soit des WSA, soit des thread.
    Mais si le programme fonctionne en local et en LAN, c'est possible que le problème provienne quand même des thread et des WSA?

    Citation Envoyé par Bousk Voir le message
    En ce cas le problème vient certainement du bind qui bind une interface spécifique.
    Je n'ai pas encore regardé ton cours en profondeur (je n'ai jamais codé en C++ j’espère que ça va pas être trop compliqué ), mais j'ai peur de pas bien comprendre cette histoire d'interface spécifique (c'est le INADDR_ANY ?).

    La valeur INADDR_ANY pour s_addr indique au système d'assigner ce socket à toutes les interfaces disponibles sur la machine, et ainsi d'accepter toutes les sources de connexion, locales et distantes. Si vous hésitez sur la valeur à assigner, vous devriez sûrement utiliser celle-ci.
    J'ai donc mis INADDR_ANY, mais le problème persiste en réseau (fonctionne parfaitement en local et LAN)

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Je ne vais pas recopier ici des chapitres de mon cours, tu peux cliquer sur le lien dans ma signature et le lire.
    Moi je suis allé le lire. Ok il est en C++ mais ça reste assez compréhensible (suffit juste d'oblitérer ces reinterpret_cast<const char*>(& networkLen) de druide celtique ) et surtout j'ai appris des trucs
    Je pensais effectivement que send/recv c'était l'équivalent du fwrite/fread (d'un côté je send, de l'autre je recv) mais en fait non. Il faut vraiment prendre le réseau comme un trou duquel on récupèrera pas forcément tout, pas forcément tout de suite.

    Il y a tout de même un petit souci: je comprends que si le client veut s'assurer que ce qu'il envoie a été reçu, il doit alors attendre un retour du serveur. Retour qui se fera de son côté par send(). Mais si le serveur envoie ce retour et qu'il s'arrête, le client ne le recevra pas. Ou alors le serveur doit ensuite attendre un retour du client pour qu'il sache que le client a reçu son retour à lui. Mais si le client envoie ce retour et s'arrête, le serveur ne le recevra pas. Ou alors le client doit ensuite attendre un retour du serveur pour qu'il sache que le serveur a bien reçu son propre retour. Mais si le serveur... ok j'arrête.
    Donc comment gérer le souci ?

    Citation Envoyé par Olocki Voir le message
    Mais si le programme fonctionne en local et en LAN, c'est possible que le problème provienne quand même des thread et des WSA?
    Possible. Mais (rappel) ton post initial disait "mon réseau ne communique pas, est-ce que ça vient de mes sockets, de mes ports fermés ou de mon firewall". Il se trouve que ça ne vient pas de là (enfin si mon code fonctionne chez-toi). Donc le souci initial est résolu. Pour le reste, il te faut maintenant apprendre à manipuler les thread et les WSA.

    Citation Envoyé par Olocki Voir le message
    Je n'ai pas encore regardé ton cours en profondeur (je n'ai jamais codé en C++ j’espère que ça va pas être trop compliqué ), mais j'ai peur de pas bien comprendre cette histoire d'interface spécifique (c'est le INADDR_ANY ?).
    Un client a besoin de dire sur quelle machine il veut connecter sa socket. Un serveur, lui, n'a pas besoin de le dire puisqu'il connecte la socket obligatoirement sur lui. La constante INADDR_ANY (qui doit probablement valoir 0) permet de spécifier au bind de ne pas chercher la machine sur le réseau, que la machine c'est celle là.
    Si maintenant un serveur tente de dire au protocole "je suis le serveur mais je me bind quand-même sur une autre machine", il est possible que le protocole passe là dessus (en considérant alors le serveur comme client potentiel de l'autre machine mais même comme ça, le truc restera un peu bancal), mais il est possible aussi qu'il t'explose à la figure.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  12. #12
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Il y a tout de même un petit souci: je comprends que si le client veut s'assurer que ce qu'il envoie a été reçu, il doit alors attendre un retour du serveur. Retour qui se fera de son côté par send(). Mais si le serveur envoie ce retour et qu'il s'arrête, le client ne le recevra pas. Ou alors le serveur doit ensuite attendre un retour du client pour qu'il sache que le client a reçu son retour à lui. Mais si le client envoie ce retour et s'arrête, le serveur ne le recevra pas. Ou alors le client doit ensuite attendre un retour du serveur pour qu'il sache que le serveur a bien reçu son propre retour. Mais si le serveur... ok j'arrête.
    Donc comment gérer le souci ?
    Tu peux faire : le client envoie, le serveur ack, quand le client reçoit l'ack il se déconnecte, le serveur voit la déconnexion.
    En pratique il y a des attentes, et de multiples envois, juste pour s'assurer qu'au moins un arrive à bon port.
    TCP permet de faire une déconnexion propre, donc tu peux détecter si la déconnexion est normale ou non. C'est une déconnexion en 4 temps derrière : http://www.tcpipguide.com/free/t_TCP...mination-2.htm mais on ne s'en soucie pas.
    En UDP il faut recréer un système similaire.


    bind assigne une interface réseau à ton socket. Tu précises l'IP quand tu as plusieurs interfaces/cartes réseau et veux en utiliser une particulière ou accepter les connexions d'une adresse particulière. Je n'ai personnellement jamais utilisé cette option.
    INADDR_ANY permet d'écouter sur toutes les interfaces disponibles.
    https://bousk.developpez.com/cours/r...iers-pas/#LI-A

    Pour la configuration du routeur, il faut rediriger un port public vers ton ip/port privé. Et il faut te connecter sur l'IP/port public du serveur.
    Si le programme fonctionne en local ou lan, le problème vient très probablement de la configuration du serveur et routeur. Mais c'est un autre sujet que je maîtrise moins.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  13. #13
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2020
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2020
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Bon, normalement j'ai bien "compris" le principe (enfin j’espère )

    Citation Envoyé par Bousk Voir le message
    Pour la configuration du routeur, il faut rediriger un port public vers ton ip/port privé. Et il faut te connecter sur l'IP/port public du serveur.
    Si le programme fonctionne en local ou lan, le problème vient très probablement de la configuration du serveur et routeur. Mais c'est un autre sujet que je maîtrise moins.
    Je vais voir par là mais normalement je pense avoir bien configuré tout cela car c'est en réalité mon problème de départ (et je suis sincèrement navré de mettre mal exprimé )
    Le serveur envoie donc bien le message mais ne reçoit pas celui du client malgré les modifications effectuées.

    En tout cas je vous dis un grand merci pour tous vos conseils et pour le temps que vous avez consacré a cette discussion.

Discussions similaires

  1. Problème de connexion Socket en TCP
    Par jerdream78 dans le forum Réseau
    Réponses: 11
    Dernier message: 26/02/2010, 12h05
  2. problème de connexion :socket
    Par alamidev dans le forum C#
    Réponses: 0
    Dernier message: 29/04/2009, 13h23
  3. Problème de connexion sous Windows Server 2003 SP2
    Par SebLeRouennais dans le forum JDBC
    Réponses: 0
    Dernier message: 07/01/2009, 15h42
  4. Problème de connexion sous windows 98
    Par aiolia_aiolos dans le forum Débuter
    Réponses: 5
    Dernier message: 21/10/2008, 14h59
  5. Problème de connexion socket
    Par stephane.julien dans le forum C#
    Réponses: 3
    Dernier message: 24/04/2008, 18h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo