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

Réseau C Discussion :

connexion winsock rame


Sujet :

Réseau C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 68
    Par défaut connexion winsock rame
    Bonjour,

    J'ai besoin de developper une application serveur sous windows qui envoie l'état d'un matériel toute les 150 msec à des clients distants.

    J'ai fait une petite appli winsock2. Je crée un socket d'écoute qui crée un socket client lorsqu'un client demande la connection. Le serveur crée un thread client qui tourne en boucle pour lire le socket client (socket non bloquant).
    Lorsque le thread client recoit une demande du client distant (16 octets), il renvoie l'état du matériel (environ 700 octets). Ceci se produit environ toutes les 150 msec.
    Dès que j'ai deux clients connectés, mon serveur me bouffe presque toute la puissance machine (un intel dual core 3GHz !), les autres programmes sur la machine rament... J'ai testé avec et sans l'option TCP_NODELAY, ca change la réactivité du système, mais pas le fait qu'il est gourmand en resources processeur.

    Qu'est ce que j'ai fait qui vous semble incorrect ? Le principe du polling sur le socket client est il en cause ? J'ai aussi essayé avec un socket bloquant, même chose.

    Merci

    Olivier

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Tu peux nous montrer le code de la boucle de réception des messages.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 68
    Par défaut
    messages windows ?
    ou reseau ?

    Voici la fonction de thread 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
    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
    void ClientFunc(LPVOID lpParameter)
    {
    	int idx = (int)lpParameter;
    	TCHAR buf[255];
    	SOCKET sock = gcf.clientStruct[idx].sd;
     
    	//init to minimum expected = message size = 1 int
    	gcf.clientStruct[idx].nDataIn = sizeof(int);
    	int nBytesReceived = 0;
    	bool bReadLength = true;		// flag to switch between reading data length and data itself
     
    	gcf.clientStruct[idx].nDataOut = 0;
    	gcf.clientStruct[idx].bSend = false;
     
    	// Thread is effectively started
    	gcf.clientStruct[idx].bClientStopped = false;
     
    	// Main Loop
    	while (gcf.clientStruct[idx].bClientRunning){
     
    	// IN buffer handling ----------------------------------------------------------------------
    		//EnterCriticalSection(&critIN); 
    		int nRead = 0;
    		//Sleep(50);
    		if (nBytesReceived < gcf.clientStruct[idx].nDataIn){// need to read
    			// read incoming buffer
    			nRead = recv(sock,(char*)gcf.clientStruct[idx].inbufferData,gcf.clientStruct[idx].nDataIn,0);
    			if (nRead > 0){// data was effectively read
    				nBytesReceived += nRead;
    				if (nBytesReceived == gcf.clientStruct[idx].nDataIn){// data correctly received
    					if (bReadLength){// the message size was received
    						// prepare for message body
    						gcf.clientStruct[idx].nDataIn = (int) ntohl( *((int*)gcf.clientStruct[idx].inbufferData)  );
    						nBytesReceived = 0;
    						}// end received message size
    					else{// received message body
    						ProcessMessage(nBytesReceived, idx);
    						gcf.clientStruct[idx].nDataIn = sizeof(int);
    						nBytesReceived = 0;
    						}// end message body
    					// switch between length and data
    					bReadLength = !bReadLength;
    					}// end data correctly received
    				}// end data has been read
    			else{// error occurred
    				DWORD err = GetLastError();
    				if (err != WSAEWOULDBLOCK){
    					//sprintf_s(buf,255,"Client thread %d network error : %d",idx,err);
    					gcf.log(buf);
    					// "real" error - cancel
    					if (err == WSAECONNRESET){
    						// Client connection terminated
    						gcf.clientStruct[idx].bSend = false;
    						gcf.clientStruct[idx].clientThreadID = 0;
    						gcf.clientStruct[idx].index = -1;
    						gcf.clientStruct[idx].bClientRunning = false;
    						gcf.nClientsNb--;
    						closesocket(gcf.clientStruct[idx].sd);
    						swprintf_s(buf,255,_T("Client connection %d terminated (receiving)"),idx);
    						gcf.log(buf);
    						}
    					//nBytesReceived = gcf.clientStruct[idx].nDataIn;
    					}// end != wouldblock
    				}// end error occured
     
    			}// end reading
    		//LeaveCriticalSection(&critIN); 
     
    	// OUT buffer handling ---------------------------------------------------------------------
    		//EnterCriticalSection(&critOUT); 
     
    		if (gcf.clientStruct[idx].bSend){// There is something to send
    			int nBytesSent = 0;
    			while (nBytesSent < gcf.clientStruct[idx].nDataOut){
    					int nSent = send(sock,(char*)(&gcf.clientStruct[idx].outbufferData[0]+nBytesSent),gcf.clientStruct[idx].nDataOut - nBytesSent,0 );
    					if (nSent == SOCKET_ERROR) {
    						// error sending
    						int err = WSAGetLastError();
    						if (err != WSAEWOULDBLOCK){// it's a "real" error
    							//sprintf_s(buf,255,"Client thread %d network error : %d",idx,err);
    							gcf.log(buf);
    							if (err == WSAECONNRESET){// connection forcibly closed
    								TCHAR buf[255];
    								nBytesSent = 0;
    								gcf.clientStruct[idx].bSend = false;
    								gcf.clientStruct[idx].clientThreadID = 0;
    								gcf.clientStruct[idx].index = -1;
    								gcf.clientStruct[idx].bClientRunning = false;
    								gcf.nClientsNb--;
    								closesocket(gcf.clientStruct[idx].sd);
    								swprintf_s(buf,255,_T("Client connection %d terminated (sending)"),idx);
    								gcf.log(buf);
    								}
    							gcf.log(_T("Unknown sending error"));
    							}// end "real" errors
    						}//end socket error
    					else{
    						nBytesSent += nSent; // add sent bytes to total
    						}
    					}// end send data
    				}// end while not finished sending			
     
    			gcf.clientStruct[idx].bSend = false;// data was sent, reset flag
     
    		// LeaveCriticalSection(&critOUT); 
     
    		}// end while ThreadRun
     
    	// Thread is exiting (Killed)
    	gcf.clientStruct[idx].bClientStopped = true;
    }
    D'abord on recoit, le recv est non bloquant, donc si il n'y a rien, on passe à la suite. La suite c'est l'envoi de données, si il y en a. Le booleen gcf.clientStruct[idx].bSend indique si il y en a.

    La réception se passe en deux temps : d'abord la taille du paquet, puis le paquet de données. Idem à l'émission.

    On recoit une requete pour envoyer les données (un code sur 4 octets - la fonction ProcessMessage trie les différentes requètes de données possibles), et on renvoie alors les données (700 octets).

    Merci,

    Olivier

  4. #4
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par oliver_mpt Voir le message
    Voici la fonction de thread client :
    gcf, c'est une globale ? Beark... Le thread a pourtant un paramètre qui est fait pour ça...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void ClientFunc(LPVOID lpParameter)
    {
    	int idx = (int)lpParameter;
    Tu accumules les gaffes. Rien ne dit qu'un int tienne dans un pointeur...

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 68
    Par défaut
    Merci pour tes réponses qui ne résolvent pas mon problème. Comme tu n'a pas l'ensemble du code, tu ne peux pas juger de la pertinence du global.
    Pour le pointeur et l'int tu as tout à fait raison.

    Olivier

    PS: j'ai eu la réponse ailleurs. Le polling actif sur un socket non bloquant est notoirement connu (de certains) pour être gourmand en processeur. On m'a suggéré d'autres solutions sur le forum Développement réseaux ici.

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

Discussions similaires

  1. Ghost Connexion Winsock.pas
    Par 0x44-0x43-0x53-0x43 dans le forum Web & réseau
    Réponses: 11
    Dernier message: 05/03/2010, 16h56
  2. Connexion Winsock et boucle infinie
    Par Pietje dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 31/10/2006, 11h51
  3. [devcpp][winsock]Ouverture de port avec plusieurs connexions
    Par Belegkarnil dans le forum Dev-C++
    Réponses: 9
    Dernier message: 10/04/2006, 13h18
  4. [VB6] Connexion avec composant Winsock
    Par Sytchev3 dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 03/04/2006, 14h07
  5. [VB6] Gérer correctement les connexions winsock
    Par Xdrei dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 25/03/2006, 12h57

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