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

Développement Discussion :

Connexion TCP Asynchrone : client C#, Serveur C++


Sujet :

Développement

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    31
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 31
    Points : 27
    Points
    27
    Par défaut Connexion TCP Asynchrone : client C#, Serveur C++
    Bonjour tout le monde,

    voici mon client C# provisoire qui fonctionne (essayé avec un serveur C#, il fonctionne) et j'essaie de faire un Serveur C++ sans succes jusqu'à present. Je vous mettrai ce que j'ai fait en C++ pour l'instant, mais pas évident de faire un poste et de choper le code de la machine virtuelle et celui de mon PC en même temps.
    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
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    using System;
    using System.Net;
    using System.Net.Sockets;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                SocketClient Application;
    
                while (true)
                {
                    Application = new SocketClient();
                    while (!Application.m_clientSocket.Connected)
                    {
                        Application = new SocketClient();
                    }
                    if (Application.m_clientSocket.Connected)
                    {
                        while (Application.m_clientSocket.Connected)
                        {
                            Application.Send("AAA\n");
                        }
                        Console.WriteLine("Connection Closed");
                    }
                }
            }
        }
    
        class SocketClient
        {
            byte[] m_dataBuffer = new byte[10];
            IAsyncResult m_result;
            public AsyncCallback m_pfnCallBack;
            public Socket m_clientSocket;
            public String richTextRxMessage;
    
            public SocketClient()
            {
                try
                {
                    // Create the socket instance
                    m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
                    // Cet the remote IP address
                    IPAddress ip = IPAddress.Parse("192.168.1.10");
                    int iPortNo = System.Convert.ToInt16("8000");
                    // Create the end point 
                    IPEndPoint ipEnd = new IPEndPoint(ip, iPortNo);
                    // Connect to the remote host
                    m_clientSocket.Connect(ipEnd);
                    if (m_clientSocket.Connected)
                    {
                        //Wait for data asynchronously 
                        WaitForData();
                    }
                }
                catch (SocketException se)
                {
                    string str;
                    str = "\nConnection failed, is the server running?\n" + se.Message;
                    Console.WriteLine(str);
                }
            }
    
    
            public void WaitForData()
            {
                try
                {
                    if (m_pfnCallBack == null)
                    {
                        m_pfnCallBack = new AsyncCallback(OnDataReceived);
                    }
                    SocketPacket theSocPkt = new SocketPacket();
                    theSocPkt.thisSocket = m_clientSocket;
                    // Start listening to the data asynchronously
                    m_result = m_clientSocket.BeginReceive(theSocPkt.dataBuffer,
                                                            0, theSocPkt.dataBuffer.Length,
                                                            SocketFlags.None,
                                                            m_pfnCallBack,
                                                            theSocPkt);
                }
                catch (SocketException se)
                {
                    Console.WriteLine("SocketException=              " + se.Message);
                }
    
            }
    
    
            public void OnDataReceived(IAsyncResult asyn)
            {
                try
                {
                    SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
                    int iRx = theSockId.thisSocket.EndReceive(asyn);
                    char[] chars = new char[iRx + 1];
                    System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
                    int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
                    System.String szData = new System.String(chars);
                    richTextRxMessage = richTextRxMessage + szData;
                    WaitForData();
                }
                catch (ObjectDisposedException)
                {
                    System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
                }
                catch (SocketException se)
                {
                    Console.WriteLine("SocketException2=              " + se.Message);
                }
            }
    
            public void Send(String mssge)
            {
                try
                {
                    Object objData = mssge;
                    byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString());
                    if (m_clientSocket != null)
                    {
                        m_clientSocket.Send(byData);
                    }
                }
                catch (SocketException se)
                {
                    Console.WriteLine(se.Message);
                }
            }
        }
    
    
        public class SocketPacket
        {
            public System.Net.Sockets.Socket thisSocket;
            public byte[] dataBuffer = new byte[1];
        }
    }

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    31
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 31
    Points : 27
    Points
    27
    Par défaut
    Voilà, apres avoir bien chercher, j'ai trouver le code nécessaire et aussi la petite commande à taper sur mon Kubuntu (sudo ufw allow 8000) .

    Bien sur, le code ne fait pour l'instant que lire et retransmettre sur la sortie console.

    Je continuerai ce poste plus tard avec le code pour envoyer des données depuis le serveur au client.

    Autre problème intervenu dans ce code, c'est le refus ulterieur de toute connexion, même apres réinitialisation de l'appli.

    Encore un probleme, c'est le while(true) qui prend énormément de ressources.

    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
    /* 
     * File:   main.cpp
     * Author: x
     *
     * Created on 3 janvier 2010, 16:51
     */
    
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <arpa/inet.h>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    #define MYPORT "8001"  // the port users will be connecting to
    #define BACKLOG 10     // how many pending connections queue will hold
    #define MAXLEN 10
    
    /*
     * 
     */
    // first, load up address structs with getaddrinfo():
    
    int main(int argc, char** argv) {
        struct addrinfo hints, *res, *p;
        struct sockaddr_storage their_addr;
        socklen_t addr_size;
        int sockfd, new_fd;
        void*buf;
        char recvbuf[MAXLEN];
    
        std::string test;
    
        int status;
        char ipstr[INET6_ADDRSTRLEN];
    
        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;
        
        if ((status = getaddrinfo("192.168.1.10", NULL, &hints, &res)) != 0) {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
            return 2;
        }
    
        printf("IP addresses for 192.168.1.10:\n\n");
    
        for(p = res;p != NULL; p = p->ai_next) {
            void *addr;
            char *ipver;
    
            // get the pointer to the address itself,
            // different fields in IPv4 and IPv6:
            if (p->ai_family == AF_INET) { // IPv4
                struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
                addr = &(ipv4->sin_addr);
                ipver = "IPv4";
            } else { // IPv6
                struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
                addr = &(ipv6->sin6_addr);
                ipver = "IPv6";
            }
    
            // convert the IP to a string and print it:
            inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
            printf("  %s: %s\n", ipver, ipstr);
        }
        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
    
        getaddrinfo(NULL, MYPORT, &hints, &res);
    
        // make a socket:
    
        sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    
        // bind it to the port we passed in to getaddrinfo():
    
        bind(sockfd, res->ai_addr, res->ai_addrlen);
    
        // now accept an incoming connection:
        listen(sockfd, BACKLOG);
        addr_size = sizeof their_addr;
        new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size);
        
        while(true)
        {
            string buffer = "";
            recv(new_fd, recvbuf, MAXLEN, 0);
            cout << "Str recu : ";
            for(int i=0;i<MAXLEN;i++)
            {
                buffer+=recvbuf[i];
            }
            cout<<buffer << endl;
        }
        freeaddrinfo(res); // free the linked list
    
        return 0;
    
    }

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    31
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 31
    Points : 27
    Points
    27
    Par défaut
    Voila, j'ai résolu pas mal de problèmes.

    Voici mon code de mon 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
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    /* 
     * File:   main.cpp
     * Author: x
     *
     * Created on 3 janvier 2010, 16:51
     */
    
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <arpa/inet.h>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <string>
    #include <pthread.h>
    
    
    
    using namespace std;
    
    #define MYPORT "8001"  // the port users will be connecting to
    #define BACKLOG 10     // how many pending connections queue will hold
    #define MAXLEN 1024
    #define MAXPLAYER 100
    #define NTHREADS 15 //le nombre de thread max gérés.
    #define errexit(code,str)                          \
        fprintf(stderr,"%s: %s\n",(str),strerror(code)); \
        exit(1);
    
    
    /*
     * 
     */
    struct thread_data
    {
       int	thread_id;
       int  sum;
       char *message;
    };
    
    void *hola(void * threadarg)
     {
        int errcode;    
        socklen_t addr_size;
        int sockfd;
        int* new_fd;
        void*buf;
        char * recvbuf = new char [MAXLEN];
        int taskid, sum;
        char *hello_msg;
        struct thread_data *my_data;
        bool test=false;
        sleep(1);
        my_data = (struct thread_data *) threadarg;
        taskid = my_data->thread_id;
        sum = my_data->sum;
        hello_msg = my_data->message;
        cout << "Thread " << taskid << ": ";
        if(hello_msg !=NULL)
        {
            cout << "MSG => ";
            cout << hello_msg;
        }
        else
            cout << "NO MESSAGE";
        cout << "  Sum="<< sum << endl;
        test=true;
        struct addrinfo hints, *res, *p;
        struct sockaddr_storage their_addr;
        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
    
        getaddrinfo(NULL, MYPORT, &hints, &res);
    
        // make a socket:
    
        sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    
        // bind it to the port we passed in to getaddrinfo():
    
        bind(sockfd, res->ai_addr, res->ai_addrlen);
    
        // now accept an incoming connection:
        cout << "Thread " << taskid <<  "will listening" << endl;
        listen(sockfd, BACKLOG);
        cout << "Thread " << taskid <<  "was listening" << endl;
    
        addr_size = sizeof their_addr;
        new_fd=new int[MAXPLAYER];
        int nbr;
        int i,j=0;
        cout << "Thread " << taskid <<  "will accept" << endl;
        new_fd[j] = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size);
        cout << "Thread " << taskid << ": " << "recv will begin" << endl;
        while(nbr=recv(new_fd[j], recvbuf, MAXLEN, 0))
        {
            recvbuf[nbr]=0;
            cout << endl << "Str recu thread nbr" << taskid << ": ";
            cout<<recvbuf;
        }
        freeaddrinfo(res); // free the linked list
       pthread_exit(NULL);
    
    }
    
    int main(int argc, char** argv) {
        int worker;
        pthread_t threads[NTHREADS];                /* holds thread info */
        int ids[NTHREADS];                          /* holds thread args */
        
        struct thread_data _session[NTHREADS];
        int status;
        char ipstr[INET6_ADDRSTRLEN];
    
        for (worker=0; worker<NTHREADS; worker++)
        {
            ids[worker]=worker;
            _session[worker].thread_id=worker;
            _session[worker].message="Hello World";
            _session[worker].sum=sizeof(_session[worker].message);
            if(0!=pthread_create(&threads[worker],NULL,hola,&_session[worker]))
                perror("impossible de créer le thread:");
       }
        while(1)
        {
            
        }
        /*
        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;
        
        if ((status = getaddrinfo("192.168.1.10", NULL, &hints, &res)) != 0) {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
            return 2;
        }
    
        printf("IP addresses for 192.168.1.10:\n\n");
    
        for(p = res;p != NULL; p = p->ai_next) {
            void *addr;
            char *ipver;
    
            // get the pointer to the address itself,
            // different fields in IPv4 and IPv6:
            if (p->ai_family == AF_INET) { // IPv4
                struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
                addr = &(ipv4->sin_addr);
                ipver = "IPv4";
            } else { // IPv6
                struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
                addr = &(ipv6->sin6_addr);
                ipver = "IPv6";
            }
    
            // convert the IP to a string and print it:
            inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
            printf("  %s: %s\n", ipver, ipstr);
        }
    //*/
        return 0;
    
    }

    En gros, lorsque je connecte un client, il se connecte et il peut envoyer de la donnée qui est bien receptionnée.

    Par contre, lorsque que je connecte un deuxieme client, il se connecte bien (c'est ce que le client me dit) mais par contre, toutes les données qu'il envoie au serveur n'arrive pas.

    Le serveur ne semble jamais recevoir de demande de connexion de la part de mon 2e client et le "accept" n'est jamais dépassé.


    La techno utilisée est de mettre chaque accepts dans des threads différents.

  4. #4
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Points : 2 161
    Points
    2 161
    Par défaut
    Citation Envoyé par Velvounet Voir le message
    La techno utilisée est de mettre chaque accepts dans des threads différents.
    Le problème vient de là: ton listen() et accept() se trouvent dans la fonction 'hola', qui semble être celle exécutée par chacun des threads. Ce n'est pas la bonne méthode.

    Normalement, tu ne dois avoir qu'un seul thread - typiquement le thread principal - qui s'occupe d'écouter sur le port (avec bind() + listen()) et d'accepter les connexions entrantes (avec accept() dans une boucle while(!shutdown)).

    Par contre tu auras effectivement un thread pour gérer chaque socket mais une fois seulement que la socket a été récupérée avec le accept dans ton thread principal.

    Dans le principe:

    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
    int main(int argc, char** argv) {
        bool shutdown = false;
        sockfd = socket(...);
        bind(sockfd, ...);
        listen(sockfd, ...);
    
        while(!shutdown) {
            new_client_socket = accept(sockfd, ...);
            pthread_create(..., ..., threadRunFunction, new_client_socket);
        }
    }
    
    void *threadRunFunction(void * clientSocketfd) {
        while(nbr=recv(clientSocketfd, recvbuf, MAXLEN, 0)) {
            // je traite les données reçues.
        }
    }
    Mon projet du moment: BounceBox, un jeu multijoueurs sur Freebox, sur PC et depuis peu sur smartphone/tablette Android.

Discussions similaires

  1. Connexion TCP Asynchrone
    Par Nico28 dans le forum Framework .NET
    Réponses: 2
    Dernier message: 28/11/2014, 09h36
  2. connexion d'un client à un serveur
    Par koukou11 dans le forum Développement
    Réponses: 0
    Dernier message: 02/03/2011, 20h26
  3. Deux connexions TCP entre un serveur et un client ?
    Par innosang dans le forum Développement
    Réponses: 4
    Dernier message: 18/12/2006, 00h33
  4. Probleme connexion Client 10g --> Serveur 8.1.7.4
    Par droopyy dans le forum Oracle
    Réponses: 9
    Dernier message: 24/03/2006, 16h05
  5. [C++] Probleme de connexion socket client à mon serveur smtp
    Par matthieu5978 dans le forum Développement
    Réponses: 2
    Dernier message: 04/12/2005, 08h19

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