Telefonino.net network
 
| HOMEPAGE | INDICE FORUM | REGOLAMENTO | ::. NEI PREFERITI .:: | RSS Forum | RSS News | NEWS web | NEWS software |
| PUBBLICITA' | | ARTICOLI | WIN XP | VISTA | WIN 7 | REGISTRI | SOFTWARE | MANUALI | RECENSIONI | LINUX | HUMOR | HARDWARE | DOWNLOAD | | CERCA nel FORUM » |

Torna indietro   WinTricks Forum > Software > Programmazione

Notices

Rispondi
 
Strumenti discussione
Vecchio 25-08-2004, 02.02.15   #1
unomichisiada
Newbie
 
Registrato: 08-07-2004
Messaggi: 47
unomichisiada promette bene
[C]NamedPipes

Salve a todos.Supponiamo di avere due applicazioni,una che fa da client e una da server in una comunicazione interprocesso mediante NamedPipes.Supponiamo che il nome della pipe sia "\\\\.\\pipe\\mypipe" per tutte le istanze sia dei client che dei server.Nelle mie intenzioni il server deve gestire le richieste di più clients e per far questo crea più thread ognuno dei quali riceve un proprio handle alla pipe (creato grazie a CreateNamedPipe con PIPE_UNLIMITED_INSTANCES come numero massimo di istanze).
Se avvio un solo server e molti client nessun problema,il server è in grado di ricevere i dati da tutti i client,se però contemporaneamente avvio un'altro server,questo non è recettivo,cioè i dati inviati dai client vengono ricevuti solo dal primo server e da lui no,mentre io vorrei che i dati inviati da qualiasi client arrivassero a tutti i server attualmente attivi,non solo ad uno.Un pò di codice così si capisce meglio:

server:


Codice:
main()
{
	DWORD dwThreadID;
	BOOL bConnected;
	HANDLE hPipe,hThread;
	while(1)
	{
		hPipe = CreateNamedPipe
(PIPENAME,PIPE_ACCESS_INBOUND,
PIPE_TYPE_BYTE | 
PIPE_WAIT,PIPE_UNLIMITED_INSTANCES,
0, 0, PIPETIMEOUT, NULL);
		if(hPipe == INVALID_HANDLE_VALUE)
			return -1;
		bConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE
			: (GetLastError() == ERROR_PIPE_CONNECTED);
		if(bConnected)
		{
			hThread =  CreateThread(NULL,0,ListenerProc,hPipe,0
,&dwThreadID);
			if(!hThread)
				return -1;
			else
				CloseHandle(hThread);
		}
		else
			CloseHandle(hPipe);
	}
	return 1;
}
DWORD WINAPI ListenerProc(LPVOID hPipe)
{
	DWORD dwBytesRead = 0;
	char buff[512];
	HANDLE hThisPipe = (HANDLE)hPipe;
	
	while (ReadFile(hThisPipe, buff, 512, &dwBytesRead, NULL))
	{
		buff[dwBytesRead] = 0;
		//processa i dati letti
		//.......
	}
	FlushFileBuffers(hThisPipe); 
	DisconnectNamedPipe(hThisPipe); 
	CloseHandle(hThisPipe); 
	return 1;
}
(Ogni client ha un solo handle alla pipe)
client:

Codice:
BOOL Connect()
{
	m_hPipe = CreateFile(PIPENAME, GENERIC_WRITE , 0, NULL,
 				OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,
 
						NULL);
	if(m_hPipe != INVALID_HANDLE_VALUE)
		return TRUE;

	return FALSE;
}
BOOL SendData(LPCSTR szData)
{
	//.......
	DWORD dwBytesWritten;
	if(WriteFile(m_hPipe, szData, (DWORD)strlen(szData), 
				 &dwBytesWritten, NULL) != FALSE &&
				 dwBytesWritten == (DWORD)strlen(szData))
		return TRUE;
	CloseHandle(m_hPipe);
	//.............
	return FALSE;
}

Nel server quando avvio due istanze del server CreateNamedPipe ritorna lo stesso
valore numerico di hPipe per entrambe però solo la prima istanza salta la
successiva ConnectNamedPipe(hPipe, NULL) quando arriva una connessione da un client
,l'altra si blocca li (e credo sia perchè l'handle è lo stesso ed è già impegnato)
ma allora perchè GetLastError() non mi da nessun errore.
Insomma voglio ottenere o di poter inviare da un client a tutti i server attivi oppure
di avvisare l'utente che non è possibile aprire due server con la stessa pipe,cosa che non
riesco a fare.

Il tutto sotto windows (xp)
___________________________________

Sai che la fortuna è una religione:tu ci credi oppure no.
unomichisiada non è collegato   Rispondi citando
Vecchio 25-08-2004, 09.05.18   #2
P8257 WebMaster
Gold Member
 
Registrato: 07-01-2002
Loc.: Milano
Messaggi: 2.863
P8257 WebMaster promette bene
Il "problema" è che l'API "CreateNamedPipe" può essere usata sia per creare una nuova istanza della pipe con gli attributi specificati (come nel tuo caso) e sia per reinstanziare una pipe già esistente, con gli stessi attributi o con nuovi attributi...

Nel tuo caso, lanciando più volte il server, non fai che reinstanziare la pipe creata dal primo server che lanci e che va a buon fine, tale pipe però è occupata già dal primo processo ed avendo lo stesso handle (dato che l'istanza della pipe è sempre una) ma accesso esclusiveo, tu non riesci ad usarla e tutti i processi server successivi rimangono inesorabilmente bloccati quando tentano di fare operazioni sulla pipe... GetLastError non restituisce errori.

La soluzione più semplice che mi viene in mente (tenendo conto che è mattina ) è quella di modificare il server in modo che la sua prima istruzione sia quella di connettersi alla pipe...

Connettendoti alla pipe riceverai un errore se la pipe non esiste (quindi sarai sicuro che non esistono altri processi server) e potrai così crearla, oppure ti connetterai con successo alla pipe creata o reinstanziata da un altro o più processi server ed in questo caso fermerai l'esecuzione avvisando l'utente che un processo server è già stato lanciato...

Bye
P8257 WebMaster non è collegato   Rispondi citando
Vecchio 25-08-2004, 18.16.13   #3
unomichisiada
Newbie
 
Registrato: 08-07-2004
Messaggi: 47
unomichisiada promette bene
Ok ho capito ci provo,grazie.
___________________________________

Sai che la fortuna è una religione:tu ci credi oppure no.
unomichisiada non è collegato   Rispondi citando
Vecchio 25-08-2004, 19.59.08   #4
unomichisiada
Newbie
 
Registrato: 08-07-2004
Messaggi: 47
unomichisiada promette bene
Quota:
La soluzione più semplice che mi viene in mente (tenendo conto che è mattina ) è quella di modificare il server in modo che la sua prima istruzione sia quella di connettersi alla pipe...
La tua soluzione è buona in teoria ma in pratica non va bene,infatti come faccio a connettermi alla pipe per testare se è possibile connettermi senza bloccarmi in attesa?Con ConnectNamedPipe non va bene perchè essendo la pipe creata in modo WAIT ConnectNamedPipe si blocca in attesa di connessioni dall'altro lato.Spero che il problema sia chiaro.Voglio trovare una funzione che mi consenta di testare se è già attivo un'altro server (che quindi occupa l'HANDLE) senza però bloccarsi in questa fase di test.
Una cosa che non mi è chiara è perchè ai thread figli di uno stesso server CreateNamedPipe assegna Handle diversi alla pipe,mentre se avvio un'altro server l'handle ritornato è lo stesso?In pratica più server ricevono la stessa istanza della pipe mentre in teoria non dovrebbe essere così.Se la funzione non si comportasse così di fatto non avrei problemi,cioè se si comportasse con i processi pari allo stesso modo in cui si comporta con i thread di uno stesso server.
___________________________________

Sai che la fortuna è una religione:tu ci credi oppure no.
unomichisiada non è collegato   Rispondi citando
Vecchio 25-08-2004, 21.15.50   #5
unomichisiada
Newbie
 
Registrato: 08-07-2004
Messaggi: 47
unomichisiada promette bene
Come non detto,ho risolto il problema con una createfile prima della createnamedpipe:
Codice:
hPipe = CreateFile(PIPENAME, GENERIC_WRITE , 0, NULL,
						 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 
						 NULL);
		if(hPipe == INVALID_HANDLE_VALUE)
			hPipe = CreateNamedPipe(PIPENAME,PIPE_ACCESS_INBOUND,
										PIPE_TYPE_BYTE | PIPE_WAIT,
										PIPE_UNLIMITED_INSTANCES, 
										0, 0, PIPETIMEOUT, NULL);
		else
		{
			CloseHandle(hPipe);
			return -1;
		}
		if(hPipe == INVALID_HANDLE_VALUE)
			return -1;
Ora però ho un'altro problema.Ho bisogno di ricavare il valore di ritorno della funzione del thread (cioè il valore che metto io dopo il return nella funzione,non il codice di uscita del processo)
Ora nella documentazione msdn ho letto che bisogna usare GetExitCodeThread() e infatti l'ho usata in questo modo:
Codice:
if (GetExitCodeThread(m_hThread,&dwExitCode))
	{
		if (dwExitCode != STILL_ACTIVE && dwExitCode < 0 )
			return FALSE;
	}
	return TRUE;
Nella pratica però non funziona,il valore che viene memorizzato in dwExitCode è sempre lo stesso (259),qualunque sia il valore con cui è uscita la funzione i callback del thread.Ne ho assoluto bisogno è non riseco in nessun modo a ricavare questo valore di ritorno.Non è che hai qualche idea?
___________________________________

Sai che la fortuna è una religione:tu ci credi oppure no.
unomichisiada non è collegato   Rispondi citando
Vecchio 27-08-2004, 17.10.44   #6
unomichisiada
Newbie
 
Registrato: 08-07-2004
Messaggi: 47
unomichisiada promette bene
Ho scoperto che 259 in realtà è il valore numerico di STILL_ACTIVE,questo significa che quando io vado a richiedere l'exit code del processo questo non è ancora terminato e invece dovrebbe dato che la funzione di callback è uscita quasi immediatamente con return -1.Anche mettendo quest'ultima istruzione come l'unica della callback (come prova) non cambiano le cose,il processo risulta comunque attivo.
___________________________________

Sai che la fortuna è una religione:tu ci credi oppure no.
unomichisiada non è collegato   Rispondi citando
Rispondi


Utenti attualmente attivi che stanno leggendo questa discussione: 1 (0 utenti e 1 ospiti)
 
Strumenti discussione

Regole di scrittura
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is ON
Gli smilies sono ON
[IMG] è ON
Il codice HTML è OFF

Vai al forum

Orario GMT +2. Ora sono le: 10.28.13.


E' vietata la riproduzione, anche solo in parte, di contenuti e grafica.
Copyright © 1999-2017 Edizioni Master S.p.A. p.iva: 02105820787 • Tutti i diritti sono riservati
L'editore NON si assume nessuna responsabilità dei contenuti pubblicati sul forum in quanto redatti direttamente dagli utenti.
Questi ultimi sono responsabili dei contenuti da loro riportati nelle discussioni del forum
Powered by vBulletin - 2010 Copyright © Jelsoft Enterprises Limited.