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 :

Canaux nommés duplex


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 266
    Par défaut Canaux nommés duplex
    Bonjour à tous,
    Je débute avec les canaux nommés,et j'ai un peu de mal à faire se que je voudrai, voilà pourquoi je viens vers vous.

    Voila je souhaiterais que mon application créé un pipe nommé en duplex:
    Je dois pouvoir communiquer avec une autre application qui se connecterai à mon pipe et avec laquelle j'ai besoin d'échanger des informations. Je dis bien échanger car l'application client peut m'envoyer des demande, mais je doit pouvoir aussi lui répondre. Mon problème étant justement de pouvoir lui répondre au moment que je souhaite, car parfois avant de lui répondre, je doit effectuer un action.

    Or dans mon code actuel, j'arrive bien a récupérer les messages de l'autre application, et arrive bien a lui répondre dans la foulé, mais pas de manière asynchrone.
    Dans le cadre de mes tests j'ai essayer de faire deux application de type tchat pour voir si j'arrive a bien discuter dans les deux sens.

    Je me suis inspiré du code de la msdn pour arriver a faire quelques chose mais mon problème et que mon code bloque sur la fonction WaitForMultipleObjects quand le client ne m'envoi rien, du coup je ne peut pas lui envoyer mon message.

    La fonction WaitForMultipleObjects ? ne doit-elle être appelé que lorsque mon serveur attend une réponse?

    Partant du code msdn qui est totalement synchrone j'ai du mal à trouver comment organiser mon code pour arriver a ce que je souhaite.

    Autre chose comment faire en sorte que l'application client ne soit pas obligé d’être lancer en tant qu'admin pour pouvoir se connecter? J’avoue ne pas avoir bien compris ce que la msdn expliquait concernant cela.

  2. #2
    Membre éclairé
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 266
    Par défaut
    Bon j'ai modifié mon code pour ne plus utilise ce WaitForMultipleObjects. Mais cette fois ci c'est le ReadFile qui est bloquant.

    voici ma nouvelle version du code dès fois que vous auriez des commentaires:

    IPC.h
    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
    #define CONNECTING_STATE 0
    #define READING_STATE 1
    #define WRITING_STATE 2
    #define BUFSIZE 4096
    #define PIPE_NAME "\\\\.\\pipe\\Knp1"
     
    typedef struct
    {
       OVERLAPPED oOverlap;
       HANDLE hPipeInst;
       TCHAR chRequest[BUFSIZE];
       DWORD cbRead;
       TCHAR chReply[BUFSIZE];
       DWORD cbToWrite;
       DWORD dwState;
       BOOL fPendingIO;
    } PIPEINST, *LPPIPEINST;
     
     
    class TForm1;
     
    class IPC : public TThread
    {
     
    private :
    	PIPEINST Pipe;
            DWORD dwErr;
       	bool fSuccess;
            LPTSTR lpszPipename;
            TForm1 * parent;
            AnsiString aEnvoyer;
            bool stop;
     
    //Methodes
    protected :
            void Gestion();
            void __fastcall Execute();
     
    public :
    	__fastcall IPC(TForm1 * p_parent, bool p_CreateSuspended = true);
    	bool CreatePipe();
            bool AttenteDeConnexionClient();
            bool CreatePipeSecurity(SECURITY_ATTRIBUTES * pSA);
            void Envoyer(AnsiString msg);
     
    };
    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
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    //-------------------------------------------------------------
    //Nom 	:	IPC
    //Role	:	Constructeur de la classe IPC
    //-------------------------------------------------------------
    __fastcall IPC::IPC(TForm1 * p_parent, bool p_CreateSuspended):
    	TThread(p_CreateSuspended),
    	parent(p_parent)
     
    {
    	aEnvoyer = "Message Par Defaut du serveur";
            stop= false;
    }
     
     
    //-------------------------------------------------------------
    //Nom 	:	CreatePipe
    //Role	:	Créer le Pipe
    //-------------------------------------------------------------
    bool IPC::CreatePipe()
    {
    	lpszPipename = TEXT(PIPE_NAME);
    	SECURITY_ATTRIBUTES   pSa;
    	// The initial loop creates several instances of a named pipe
    	// along with an event object for each instance.  An
    	// overlapped ConnectNamedPipe operation is started for
    	// each instance.
     
    	if (!CreatePipeSecurity(&pSa))
    	{
    		dwErr = GetLastError();
    		printf("CreatePipeSecurity failed w/err 0x%08lx\n", dwErr);
    		return 0;
    	}
     
    	Pipe.hPipeInst = CreateNamedPipe(
    		lpszPipename,             // Pipe name.
    		PIPE_ACCESS_DUPLEX,         // The pipe is duplex; both server and
    		// client processes can read from and
    		// write to the pipe
    		PIPE_TYPE_MESSAGE |         // Message type pipe
    		PIPE_READMODE_MESSAGE |     // Message-read mode
    		PIPE_WAIT,                  // Blocking mode is enabled
    		PIPE_UNLIMITED_INSTANCES,   // Max. instances
    		BUFSIZE,                // Output buffer size in bytes
    		BUFSIZE,                // Input buffer size in bytes
    		NMPWAIT_USE_DEFAULT_WAIT,   // Time-out interval
    		&pSa                         // Security attributes
    		);       // default security attributes
     
    	if (Pipe.hPipeInst == INVALID_HANDLE_VALUE)
    	{
    		dwErr = GetLastError();
    		printf("CreateNamedPipe failed with %d.\n", GetLastError());
    		return 0;
    	}
    }
     
    //-------------------------------------------------------------
    //Nom 	:	AttenteDeConnexionClient
    //Role	:	Attent qu'un client se connect
    //-------------------------------------------------------------
    bool IPC::AttenteDeConnexionClient()
    {
    	// Wait for the client to connect.
        	wprintf(L"Waiting for the client's connection...\n");
        	if (!ConnectNamedPipe(Pipe.hPipeInst, NULL))
        	{
            	if (ERROR_PIPE_CONNECTED != GetLastError())
            	{
                		dwErr = GetLastError();
                		wprintf(L"ConnectNamedPipe failed w/err 0x%08lx\n", dwErr);
                            return false;
            	}
        	}
        	wprintf(L"Client is connected.\n");
            Pipe.dwState = READING_STATE;
            return true;
    }
     
    //-------------------------------------------------------------
    //Nom 	:	Gestion
    //Role	:	Gère l'envoi et la reception des données
    //-------------------------------------------------------------
    void IPC::Gestion()
    {
    	if (Pipe.dwState == READING_STATE)
    	{
    		BOOL fFinishRead = FALSE;
    		do
    		{
    			wchar_t chRequest[BUFSIZE];
    			DWORD cbRequest, cbRead;
    			cbRequest = sizeof(chRequest);
     
    			fFinishRead = ReadFile(
    				Pipe.hPipeInst,     // Handle of the pipe
    				chRequest,      // Buffer to receive data
    				cbRequest,      // Size of buffer in bytes
    				&cbRead,        // Number of bytes read
    				NULL            // Not overlapped I/O
    				);
     
    			if (!fFinishRead && ERROR_MORE_DATA != GetLastError())
    			{
    				dwErr = GetLastError();
    				wprintf(L"ReadFile from pipe failed w/err 0x%08lx\n", dwErr);
    				stop = true;
                                    return;
    			}
     
    			wprintf(L"Receive %ld bytes from client: \"%s\"\n", cbRead, chRequest);
                            if ( parent != NULL)
                            	parent->Reception(AnsiString(chRequest));
     
    		} while (!fFinishRead); // Repeat loop if ERROR_MORE_DATA
    	}
    	else if (Pipe.dwState == WRITING_STATE)
    	{
    		//
    		// Send a response from server to client.
    		//
     
                    strcpy( Pipe.chReply, TEXT(aEnvoyer.c_str()) );
    		Pipe.cbToWrite = (lstrlen(Pipe.chReply)+1)*sizeof(TCHAR);
                    DWORD cbWritten;
     
    		if (!WriteFile(
    					Pipe.hPipeInst,     // Handle of the pipe
    					Pipe.chReply,     // Buffer to write
    					Pipe.cbToWrite,     // Number of bytes to write
    					&cbWritten,     // Number of bytes written
    					NULL            // Not overlapped I/O
    					))
    		{
    			dwErr = GetLastError();
    			wprintf(L"WriteFile to pipe failed w/err 0x%08lx\n", dwErr);
    			stop = true;
                            return;
    		}
     
    		wprintf(L"Send %ld bytes to client: \"%s\"\n", Pipe.cbToWrite, Pipe.cbToWrite);
     
    		// Flush the pipe to allow the client to read the pipe's contents
    		// before disconnecting. Then disconnect the client's connection.
    		FlushFileBuffers(Pipe.hPipeInst);
                    Pipe.dwState == READING_STATE;
    	}
    }
     
    //-------------------------------------------------------------
    //Nom 	:	Execute
    //Role	:	Action du thread en boucle
    //-------------------------------------------------------------
    void __fastcall IPC::Execute()
    {
    	if ( CreatePipe())
    	{
            	if ( AttenteDeConnexionClient())
                    {
    			while (!stop)
    			{
    				Gestion();
                            }
     
    		}
                    DisconnectNamedPipe(Pipe.hPipeInst);
    	}
    }
     
     
    //-------------------------------------------------------------
    //Nom 	:	Envoyer
    //Role	:	Modifi la chaine a envoyer
    //-------------------------------------------------------------
    void IPC::Envoyer(AnsiString msg)
    {
    	aEnvoyer = msg;
            Pipe.dwState = WRITING_STATE;
    }
     
    //-------------------------------------------------------------
    //Nom 	:	CreatePipeSecurity
    //Role	:	Creer la securité du pipe
    //-------------------------------------------------------------
    bool IPC::CreatePipeSecurity(SECURITY_ATTRIBUTES * pSA)
    {
        BOOL fSucceeded = TRUE;
        DWORD dwError = ERROR_SUCCESS;
     
        TCHAR * szSD = TEXT("D:")       // Discretionary ACL
            TEXT("(D;OICI;GA;;;BG)")     // Deny access to 
                                         // built-in guests
            TEXT("(D;OICI;GA;;;AN)")     // Deny access to 
                                         // anonymous logon
            TEXT("(A;OICI;GRGWGX;;;AU)") // Allow 
                                         // read/write/execute 
                                         // to authenticated
                                         // users
            TEXT("(A;OICI;GA;;;BA)");    // Allow full control 
                                         // to administrators
     
        if (NULL == pSA)
            return FALSE;
     
        if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
                    szSD,
                    SDDL_REVISION_1,
                    &(pSA->lpSecurityDescriptor),
                    NULL))
        {
            fSucceeded = FALSE;
            dwError = GetLastError();
        }
        else
        {
     
        	// Allocate the memory of SECURITY_ATTRIBUTES.
        	pSA = (PSECURITY_ATTRIBUTES)LocalAlloc(LPTR, sizeof(*pSA));
        	if (pSA == NULL)
        	{
            	fSucceeded = FALSE;
            	dwError = GetLastError();
        	}
       	else
        	{
     
        		pSA->nLength = sizeof(*pSA);
        		pSA->bInheritHandle = FALSE;
        	}
         }
     
        // Clean up the allocated resources if something is wrong.
        if (!fSucceeded)
        {
            SetLastError(dwError);
        }
     
        return fSucceeded;
    }

  3. #3
    Membre éclairé
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Février 2011
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 266
    Par défaut
    Bon finalement j'ai reussi a faire un truc avec la fonction "PeekNamedPipe".
    si ça interesse des gens :
    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
    //-------------------------------------------------------------
    //Nom 	:	Gestion
    //Role	:	Gère l'envoi et la reception des données
    //-------------------------------------------------------------
    void IPC::Gestion()
    {
    	lock->Enter();
    	if (Pipe.dwState == READING_STATE)
    	{
    		BOOL fFinishRead = FALSE;
    		do
    		{
    			wchar_t chRequest[BUFSIZE];
    			DWORD cbRequest, cbRead;
    			cbRequest = sizeof(chRequest);
                            DWORD lpNumberOfBytesRead = 0;
                            // Test the total number of bytes available to be read from the pipe
    			PeekNamedPipe( Pipe.hPipeInst ,NULL, 0, NULL, &lpNumberOfBytesRead, NULL);
    			if (lpNumberOfBytesRead == 0)
                            {
                            	fFinishRead = true;
                            	continue;
                            }
     
     
     
    			fFinishRead = ReadFile(
    				Pipe.hPipeInst,     // Handle of the pipe
    				chRequest,      // Buffer to receive data
    				cbRequest,      // Size of buffer in bytes
    				&cbRead,        // Number of bytes read
    				NULL            // Not overlapped I/O
    				);
     
    			if (!fFinishRead && ERROR_MORE_DATA != GetLastError())
    			{
    				dwErr = GetLastError();
                                    AnsiString msg = msg.sprintf("ReadFile from pipe failed w/err 0x%08lx\n", dwErr);
            			if ( parent != NULL)
            				parent->Reception(msg) ;
    				stop = true;
                                    break;
    			}
                            AnsiString msg = msg.sprintf("Receive %ld bytes from client: \"%s\"", cbRead, chRequest);
                            if ( parent != NULL)
                            	parent->Reception(msg) ;
     
    		} while (!fFinishRead); // Repeat loop if ERROR_MORE_DATA
    	}
    	else if (Pipe.dwState == WRITING_STATE)
    	{
    		//
    		// Send a response from server to client.
    		//
     
                    strcpy( Pipe.chReply, TEXT(aEnvoyer.c_str()) );
    		Pipe.cbToWrite = (lstrlen(Pipe.chReply)+1)*sizeof(TCHAR);
                    DWORD cbWritten;
     
    		if (!WriteFile(
    					Pipe.hPipeInst,     // Handle of the pipe
    					Pipe.chReply,     // Buffer to write
    					Pipe.cbToWrite,     // Number of bytes to write
    					&cbWritten,     // Number of bytes written
    					NULL            // Not overlapped I/O
    					))
    		{
    			dwErr = GetLastError();
                            AnsiString msg = msg.sprintf("WriteFile to pipe failed w/err 0x%08lx\n", dwErr);
                            if ( parent != NULL)
                            	parent->Reception(msg) ;
    			stop = true;
    		}
                    else
                    {
                    	AnsiString msg = msg.sprintf("Send %ld bytes to client: \"%s\"\n", Pipe.cbToWrite, Pipe.chReply);
                            if ( parent != NULL)
                            	parent->Reception(msg) ;
     
    			// Flush the pipe to allow the client to read the pipe's contents
    			// before disconnecting. Then disconnect the client's connection.
    			FlushFileBuffers(Pipe.hPipeInst);
                    	Pipe.dwState == READING_STATE;
                    }
    	}
            lock->Release();
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de connexion avec canaux nommés
    Par FMJ dans le forum Administration
    Réponses: 8
    Dernier message: 01/06/2010, 17h18
  2. Erreur : Fournisseur de canaux nommé
    Par laetitia02 dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 04/12/2009, 14h32
  3. Réponses: 10
    Dernier message: 07/05/2009, 13h33
  4. ASP +SQL SRV 2005 : pb canaux nommés
    Par phoenix75 dans le forum ASP.NET
    Réponses: 1
    Dernier message: 02/06/2008, 11h18
  5. Réponses: 4
    Dernier message: 05/05/2006, 15h45

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