IL process l'ho incluso, ma quando compilo mi dice undeclared identifier.
Non avresti da mostrarmi un esempio di thread abbastanza semplice?
IL process l'ho incluso, ma quando compilo mi dice undeclared identifier.
Non avresti da mostrarmi un esempio di thread abbastanza semplice?
http://www.navimel.com
La disumanità del computer sta nel fatto che, una volta programmato(da me) e messo in funzione, FA QUEL CAZZO CHE VUOLE!!!
è da pazzi!Originariamente inviato da Johnny_Depp
leggi attentamente questo documento, (redatto da un folle :gren: )
in fondo alla pagina che ti linko trovi anche i corrispettivi
comandi/funzioni UNIX WINDOWS
http://members.xoom.virgilio.it/bsd_...erebrolesi.txt
E lunghissimo![]()
La stupidità umana e l'universo sono infinite.
Della seconda non sono certo(Einstein)
Gnu/Linux User
codice:#define _MT #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <process.h> CRITICAL_SECTION cs; int run; void UnThreadInutile(void * args); int main() { char * parametro_per_thread_1 = "Salve, sono il secondo thread\n"; char * parametro_per_thread_2 = "Salve, sono il terzo thread\n"; run = 0; InitializeCriticalSection(&cs); printf( "Salve, sono il primo thread\n" "Quando non ne puoi piu premi un tasto\n"); Sleep(4000); if(_beginthread(UnThreadInutile, 0, parametro_per_thread_1) == -1) exit(1); if(_beginthread(UnThreadInutile, 0, parametro_per_thread_2) == -1) exit(1); _getch(); return 0; } void UnThreadInutile(void * args) { while(!run) { EnterCriticalSection(&cs); printf((char*)args); LeaveCriticalSection(&cs); } }
Se usi visual studio vai nelle impostazioni del linker e spunta "Ignore default libraries" e linka LIBCMT.LIB
Oppure nelle impostazioni del compilatore (project/settings/C-C++ combo category=code generation) scegli Multithreaded come runtime library
OK alla fine sono riuscito a creare il thread con CreateThread e mi creo 2 thread su queste 2 funzioni:
hThreads[0] = CreateThread(NULL,0,AcceptConn,(LPVOID)0,NULL,&id[0]);
hThreads[1] = CreateThread(NULL,0,RecDati,(LPVOID)0,NULL,&id[1]);
//per la connessione
DWORD WINAPI AcceptConn(LPVOID n)
{
while(true){//accettazione connessione
printf("STO ASPETTANDO UNA CONNESSIONE\n");
temp=accept(sock,&addr,NULL);
sock=temp;
connesso++;
printf("HO ACCETTATO UNA CONNESSIONE\n");
}
return (DWORD)n;
}
//per il ricevimento dei dati
DWORD WINAPI RecDati(LPVOID n)
{
while(true){//ricevimento dati
if (connesso==0)
continue;
printf("STO ASPETTANDO CHE MI ARRIVINO DATI\n");
res=recv(sock,buf,100,0);
if(res==0||res==WSAECONNRESET||res==WSAECONNABORTE D){
printf("Client terminated connection\n");
connesso--;
break;
}
_flushall();//probably not needed
printf("Recieved string: %s\n",buf);
}
return (DWORD)n;
}
Il mio problema ora è che all'inizio si ferma in attesa della connessione, poi una volta accettata la connessione l'accept e il recv
vengono superati entrando cosi' in un ciclo continuo...
Ho fatto un po' di prove e sono giunto alla conclusione che la causa è il thread.
Il mio obbiettivo è quello di fare in modo che il server possa accettare piu' connessioni e ricevere messaggi dai client connessi.
Non è che mi sapresti dare una spiegazione?:master:
Grazie
http://www.navimel.com
La disumanità del computer sta nel fatto che, una volta programmato(da me) e messo in funzione, FA QUEL CAZZO CHE VUOLE!!!
Il tuo schema di server è piuttosto lacunoso, normalmente un server non fa polling inutili, lo schema è il seguente
Un thread chiamato dispatcher ha il compito di eseguire una accept, e lanciare un thread che si occupi di gestire la socket ottenuta, dopo di che riinizia il loop.
A meno che non sia utile conoscere il valore di ritorno dei thread worker, è meglio creare thread detached, oppure creare gia da subito un pool di thread e riciclare sempre quelli.codice:WHILE TRUE { SOCK = ACCEPT (QUALCOSA) LANCIA_THREAD (SOCK) }
Con CreateThread devi eliminare gli zombie a mano, eventualmente creando un ulteriore thread con il compito di prelevare i valori di ritorno degli altri thread.... _beginthread usa dei meccanismi a runtime che liberano automaticamente le risorse inusate.
Questo è lo schema di un semplice server echo in ascolto sulla porta 10101, di solito tutti i server, anche i piu complessi non sono altro che estensioni di un server echo, per cui basta riciclare il template.
codice:#define SERVERPORT 10101 /* la porta TCP da usare */ #define MAX_CONN_PENDING SOMAXCONN /* max connessioni in attesa del server */ #define MAXHOSTNAME 255 #include <winsock2.h> #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <process.h> void echo(void* arg) { SOCKET sock = (SOCKET)arg; char buffer[80]; int rd; while(rd = recv(sock, buffer, sizeof(buffer), 0), rd > 0) { send(sock, buffer , rd,0); } closesocket(sock); _endthread(); } int main () { int sfd, tfd; int i; struct sockaddr_in sa, isa; struct hostent *hp; //code from MSDN //INIZIALIZZAZIONE WINSOCK WORD wVersionRequested; WSADATA wsaData; int err; char localhost[MAXHOSTNAME]; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ printf("Necessaria versione 2 di winsock\n"); return 1; } /* Confirm that the WinSock DLL supports 2.2.*/ /* Note that if the DLL supports versions greater */ /* than 2.2 in addition to 2.2, it will still return */ /* 2.2 in wVersion since that is the version we */ /* requested. */ if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ printf("Necessaria versione 2 di winsock\n"); WSACleanup( ); return 1; } //FINE INIZIALIZZAZIONE WINSOCK /* chiede l'indirizzo del local host */ gethostname(localhost,MAXHOSTNAME); if ((hp=gethostbyname(localhost))==NULL) { perror("Impossibile ottenere nome host locale\n"); exit(1); } /* inserisce il socket number dentro la struttura del socket */ sa.sin_port=htons((short int) SERVERPORT); /* costruisce la struttura che contiene l'indirizzo del local host */ memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); sa.sin_family=hp->h_addrtype; /* richiede un descrittore di socket */ if (( sfd=socket(hp->h_addrtype, SOCK_STREAM, 0))<0 ) { perror ("errore apertura socket \n"); exit(1); } /* fa il bind alla service port */ if (bind(sfd,(struct sockaddr*) &sa, sizeof (sa))<0) { perror("bind rifiutato\n"); exit(1); } /* massimo numero di connessioni accettate */ listen(sfd, MAX_CONN_PENDING); /* SERVER LOOP */ while (1) { i=sizeof (isa); if (( tfd=accept(sfd,(struct sockaddr*) &isa, &i))<0) { perror("errore accept \n"); exit(1); } /* in tfd ho il file descriptor della connessione */ if(_beginthread(echo,0,(void*)tfd) == -1) closesocket(tfd); } return 0; }
Ho risolto il problema usando lo schema che mi hai consigliato e ora funziona tutto come volevo.
WHILE TRUE
{
SOCK = ACCEPT (QUALCOSA)
LANCIA_THREAD (SOCK)
}
Cmq i thread creati con CreateThread vengono distrutti in automatico infatti se vai a vedere sui processi e aggiungi in visualizza > colonne "thread" noterai che aumentano e diminuiscono senza bisogno di chiuderli manualmente.
Grazie per l'aiuto ciao :mavieni:
http://www.navimel.com
La disumanità del computer sta nel fatto che, una volta programmato(da me) e messo in funzione, FA QUEL CAZZO CHE VUOLE!!!
Ti sbagli, se leggi bene l'msdn vedrai che un thread morto rimane in uno stato Zombie finchè tutti gli handle al thread non sono stati chiusi MANUALMENTE
Anche se sono lungi dall'essere un esperto di IPC su windows posso dire che 'quasi sicuramente' la chiusura del socket deve essere manuale. Certo puoi avere l'effetto automatizzato in C++ usando il sistema distruttore/costruttore e di sicuro avresti qualcosa di più efficace (cosi come puoi crearti una piccola interfaccia per creare processi on the fly).
bye
There are 10 kinds of people in the world: who knows the binary numeration and who not