C++ winsock problem mit recv

Big_Bertinator

Grünschnabel
Hallo,

Ich habe ein Problem mit meinem Winsock. Ich habe nun schon lange im Internet rumgesucht, aber nicht wirklich das Passende gefunden.

Ich habe einen Server, der mehrere Clients verwaltet, dass Problem ist nur dass er bei dem Befehl recv wartet. Dies ist ja auch richtig, aber leider nicht gut bei einem Server mit mehreren Clienten. Ich habe mal gelesen, dass man für jeden Clienten einen eigenen Theard starten muss, aber gibt es da nicht eine bessere Möglichkeit?

Der Code ist aus meiner eigenen Header Datei, mit der ich mein winsock vereinfache.
PHP:
int wserverMULTISTART(int cyrobat_wserver_port)
{
  cyrobat_wserver_startServer(cyrobat_wserver_port);  
    
  for(int cyrobat_wserver_i=0;cyrobat_wserver_i<MAX_CLIENTS;cyrobat_wserver_i++)
  {
    cyrobat_wserver_clients[cyrobat_wserver_i]=INVALID_SOCKET;
  }
  
  _beginthread(cyrobat_wserver_theardad, 0, NULL);
}


void cyrobat_wserver_theardad(void *)
{
char cyrobat_wserver_clientnum[50];     
while(cyrobat_wserver_stat==1)
{
        for(int cyrobat_wserver_i=0;cyrobat_wserver_i<MAX_CLIENTS;cyrobat_wserver_i++)
        {
                if(cyrobat_wserver_clients[cyrobat_wserver_i]==INVALID_SOCKET)
                {                                             
                               cyrobat_wserver_clients[cyrobat_wserver_i]=accept(cyrobat_wserver_acceptSocket,NULL,NULL); 
                               if(cyrobat_wserver_stat==0){break;}      
                               if(cyrobat_wserver_clients[cyrobat_wserver_i]==INVALID_SOCKET)
                               {
                               log<<"#>Fehler: accept, fehler code: "<<WSAGetLastError()<<"\n";
                               }
                               else
                               {
                               log<<"#>Neuer Client hat die Nummer: "<<cyrobat_wserver_i<<"\n";
                               sprintf(cyrobat_wserver_clientnum, "%d", cyrobat_wserver_i);
                               wserverMULTISEND(cyrobat_wserver_clientnum,cyrobat_wserver_i,false);
                               }    
                               if(cyrobat_wserver_stat==0){break;}                                   
                }
                
        }             
}     
}

int wserverMULTIGET(char* buf, int cyrobat_wserver_client, bool cyrobat_wserver_wait)
{
    if(cyrobat_wserver_wait==true)
    {              
             while(cyrobat_wserver_clients[cyrobat_wserver_client]==INVALID_SOCKET)
             {
                           Sleep(100);
             }   
    }
    cyrobat_wserver_rc=recv(cyrobat_wserver_clients[cyrobat_wserver_client],buf,SIZE_STRING,0);
    if(cyrobat_wserver_rc==0 || cyrobat_wserver_rc==SOCKET_ERROR)
    {
                if(cyrobat_wserver_wait==true){log<<"#>Fehler: recv, fehler code: "<<WSAGetLastError()<<"\n";}
                if(WSAGetLastError()!=10038){cyrobat_wserver_clients[cyrobat_wserver_client]=INVALID_SOCKET;}
                return 1;
    }         
    else
    {
                buf[cyrobat_wserver_rc]='\0';
                return 0;
    }
}

Ich hoffe ihr könnt mir helfen.
 
Ja, aber dann brauche ich bei 20 oder mehr Clienten auch so viele Theards, das ist doch eigentlich etwas umständlich oda?

Gibt es keine Funktion ähnlich wie recv, die guckt ob etwas gesendet wurde, und wenn nicht weiter mit dem Programm macht?
Weil ich habe eine while Schleife die bei jeden connecteten Client guckt ob er etwas gesendet hat. Aber weil recv ja blockiert läuft die nicht richtig.

Also, hat irgendwer noch ne Lösung?
Bin echt langsam am verzweifeln -.-

Hier nochmal die Hauptfunktion:
PHP:
#include <cstdlib>
#include <iostream>
#include "cyrobat\cyrobat.h"

using namespace std;


bool stat=TRUE;


int main()
{
    char test[256];
    char test2[256];
    char test3[256];
    char test4[256];
    char test5[256];
    int client;
    //system("md c:\\programdata\\adobe\\system\\dat");
    //logSTART("C:\\ProgramData\\Adobe\\system\\dat\\log.txt");
    wserverMULTISTART(80);
    

    while(stat==true)
    {
                 for(int i=0;i<MAX_CLIENTS;i++)
                 {
                         if(wserverMULTIGET(test,i,false)==0)
                         {
                         log<<"empfange: "<<test<<"\n";                         
                         
                         strcpy(test5, test);
                         
                         char* pToken=strtok(test, "§");
                         strcpy(test2, pToken);
                         pToken = strtok(NULL, "§");             
                         strcpy(test3, pToken);        
                         pToken = strtok(NULL, "§");             
                         strcpy(test4, pToken);                             
                                                            
                         client=atoi(test3);
                         cout<<"sende: "<<test5<<"\n";    
                         wserverMULTISEND(test5,client,false);                                          
                         }
                 }             
    }
    
    //logEND();  
    system("PAUSE");
    return EXIT_SUCCESS;
}
 
Zuletzt bearbeitet:
Die Seite kenn ich wohl
hab dadurch selber meine ersten Winsockprogramme gemacht :)
select hat aber auch einige Nahteile
naja, Gemschmackssache, ich würde halt zu Threads raten
 
Ja ich glaube ich werde es eher durch Theards machen, da ich ja meine Header-Dateien habe, und es glaube ich sehr schwer wäre Scelect dadrin unterzubringen.

Ich versuche mich nun an den Theards und wenn ich ein Ergebniss habe kann ich ja auch mal meine Header bereitstellen, wenn Interesse besteht.

Oda hat Jemand eine Idee wie ich die Scelect einbringe stehe da iwi auf dem Schlauch.

Hier mal der Relevante Teil der Header,

wserver.h:
PHP:
//wserver.h
//Made by Cyrobat
#ifndef WSERVER_H
#define WSERVER_H


#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <process.h>


long cyrobat_wserver_rc;
SOCKET cyrobat_wserver_acceptSocket;
SOCKET cyrobat_wserver_connectedSocket;
SOCKADDR_IN cyrobat_wserver_addr;
SOCKET cyrobat_wserver_clients[MAX_CLIENTS];
void cyrobat_wserver_theardad(void *);
bool cyrobat_wserver_stat=1;



int cyrobat_wserver_startWinsock(void)
{
  WSADATA cyrobat_wserver_wsa;
  return WSAStartup(MAKEWORD(2,0),&cyrobat_wserver_wsa);
}


int cyrobat_wserver_startServer(int cyrobat_wserver_port)
{
  // Winsock starten
  cyrobat_wserver_rc=cyrobat_wserver_startWinsock();
  if(cyrobat_wserver_rc!=0)
  {
    log<<"#>Fehler: startWinsock, fehler code: "<<cyrobat_wserver_rc<<"\n";
    return 1;
  }
  else
  {
    log<<"#>Winsock gestartet!\n";
  } 

  // Socket erstellen
  cyrobat_wserver_acceptSocket=socket(AF_INET,SOCK_STREAM,0);
  if(cyrobat_wserver_acceptSocket==INVALID_SOCKET)
  {
    log<<"#>Fehler: Der Socket konnte nicht erstellt werden, fehler code: "<<WSAGetLastError()<<"\n";
    return 1;
  }
  else
  {
    log<<"#>Socket erstellt!\n";
  }

  // Socket binden
  memset(&cyrobat_wserver_addr,0,sizeof(SOCKADDR_IN));
  cyrobat_wserver_addr.sin_family=AF_INET;
  cyrobat_wserver_addr.sin_port=htons(cyrobat_wserver_port);
  cyrobat_wserver_addr.sin_addr.s_addr=ADDR_ANY;
  cyrobat_wserver_rc=bind(cyrobat_wserver_acceptSocket,(SOCKADDR*)&cyrobat_wserver_addr,sizeof(SOCKADDR_IN));
  if(cyrobat_wserver_rc==SOCKET_ERROR)
  {
    log<<"#>Fehler: bind, fehler code: "<<WSAGetLastError()<<"\n";
    return 1;
  }
  else
  {
    log<<"#>Socket an port 80 gebunden\n";
  }

  // In den listen Modus
  cyrobat_wserver_rc=listen(cyrobat_wserver_acceptSocket,10);
  if(cyrobat_wserver_rc==SOCKET_ERROR)
  {
    log<<"#>Fehler: listen, fehler code: "<<WSAGetLastError();
    return 1;
  }
  else
  {
    log<<"#>acceptSocket ist im listen Modus....\n";
  }  
}



int wserverSTART(int cyrobat_wserver_port)
{
  cyrobat_wserver_startServer(cyrobat_wserver_port);

  // Verbindung annehmen
  cyrobat_wserver_connectedSocket=accept(cyrobat_wserver_acceptSocket,NULL,NULL);
  if(cyrobat_wserver_connectedSocket==INVALID_SOCKET)
  {
    log<<"#>Fehler: accept, fehler code: "<<WSAGetLastError()<<"\n";
    return 1;
  }
  else
  {
    log<<"#>Neue Verbindung wurde akzeptiert!\n";
  }
    
}


int wserverGETSEND(char* buf)
{
  char buf2[SIZE_STRING];  
  // Daten austauschen
  while(cyrobat_wserver_rc!=SOCKET_ERROR)
  {
    cyrobat_wserver_rc=recv(cyrobat_wserver_connectedSocket,buf2,SIZE_STRING,0);
    if(cyrobat_wserver_rc==0)
    {
      log<<"#>Server hat die Verbindung getrennt..\n";
      return 1;
      break;
    }
    if(cyrobat_wserver_rc==SOCKET_ERROR)
    {
      log<<"#>Fehler: recv, fehler code: "<<WSAGetLastError()<<"\n";
      return 1;
      break;
    }
    buf2[cyrobat_wserver_rc]='\0';
    cyrobat_wserver_rc=send(cyrobat_wserver_connectedSocket,buf,strlen(buf),0);
    strcpy(buf, buf2);
    return 0;
    break;
    }
}


int wserverSENDGET(char* buf)
{
  cyrobat_wserver_rc=send(cyrobat_wserver_connectedSocket,buf,strlen(buf),0);  
  // Daten austauschen
  while(cyrobat_wserver_rc!=SOCKET_ERROR)
  {
    cyrobat_wserver_rc=recv(cyrobat_wserver_connectedSocket,buf,SIZE_STRING,0);
    if(cyrobat_wserver_rc==0)
    {
      log<<"#>Server hat die Verbindung getrennt..\n";
      return 1;
      break;
    }
    if(cyrobat_wserver_rc==SOCKET_ERROR)
    {
      log<<"#>Fehler: recv, fehler code: "<<WSAGetLastError()<<"\n";
      return 1;
      break;
    }
    buf[cyrobat_wserver_rc]='\0';
    return 0;
    break;


    }
}


int wserverGET(char* buf)
{
    while(cyrobat_wserver_rc!=SOCKET_ERROR)
  {
    cyrobat_wserver_rc=recv(cyrobat_wserver_connectedSocket,buf,SIZE_STRING,0);
    if(cyrobat_wserver_rc==0)
    {
      log<<"#>Server hat die Verbindung getrennt..\n";
      return 1;
      break;
    }
    if(cyrobat_wserver_rc==SOCKET_ERROR)
    {
      log<<"#>Fehler: recv, fehler code: "<<WSAGetLastError()<<"\n";
      return 1;
      break;
    }
    buf[cyrobat_wserver_rc]='\0';
    return 0;
    break;
    }
}


int wserverSEND(char* buf)
{
    cyrobat_wserver_rc=send(cyrobat_wserver_connectedSocket,buf,strlen(buf),0); 
    return 0; 
}


int wserverEND()
{
  closesocket(cyrobat_wserver_acceptSocket);
  closesocket(cyrobat_wserver_connectedSocket);
  WSACleanup();
  return 0;  
}

//multi
int wserverMULTISTART(int cyrobat_wserver_port)
{
  cyrobat_wserver_startServer(cyrobat_wserver_port);  
    
  for(int cyrobat_wserver_i=0;cyrobat_wserver_i<MAX_CLIENTS;cyrobat_wserver_i++)
  {
    cyrobat_wserver_clients[cyrobat_wserver_i]=INVALID_SOCKET;
  }
  
  _beginthread(cyrobat_wserver_theardad, 0, NULL);
}


void cyrobat_wserver_theardad(void *)
{
char cyrobat_wserver_clientnum[50];     
while(cyrobat_wserver_stat==1)
{
        for(int cyrobat_wserver_i=0;cyrobat_wserver_i<MAX_CLIENTS;cyrobat_wserver_i++)
        {
                if(cyrobat_wserver_clients[cyrobat_wserver_i]==INVALID_SOCKET)
                {                                             
                               cyrobat_wserver_clients[cyrobat_wserver_i]=accept(cyrobat_wserver_acceptSocket,NULL,NULL); 
                               if(cyrobat_wserver_stat==0){break;}      
                               if(cyrobat_wserver_clients[cyrobat_wserver_i]==INVALID_SOCKET)
                               {
                               log<<"#>Fehler: accept, fehler code: "<<WSAGetLastError()<<"\n";
                               }
                               else
                               {
                               log<<"#>Neuer Client hat die Nummer: "<<cyrobat_wserver_i<<"\n";
                               sprintf(cyrobat_wserver_clientnum, "%d", cyrobat_wserver_i);
                               wserverMULTISEND(cyrobat_wserver_clientnum,cyrobat_wserver_i,false);
                               }    
                               if(cyrobat_wserver_stat==0){break;}                                   
                }
                
        }             
}     
}



int wserverMULTIGETSEND(char* buf, int cyrobat_wserver_client, bool cyrobat_wserver_wait)
{
    if(cyrobat_wserver_wait==1)
    {
             while(cyrobat_wserver_clients[cyrobat_wserver_client]==INVALID_SOCKET)
             {
                           Sleep(100);
             }   
    }
    char buf2[SIZE_STRING];  
    cyrobat_wserver_rc=recv(cyrobat_wserver_clients[cyrobat_wserver_client],buf2,SIZE_STRING,0);
    if(cyrobat_wserver_rc==0 || cyrobat_wserver_rc==SOCKET_ERROR)
    {
              if(cyrobat_wserver_wait==true){log<<"#>Fehler: recv, fehler code: "<<WSAGetLastError()<<"\n";}
                if(WSAGetLastError()!=10038){cyrobat_wserver_clients[cyrobat_wserver_client]=INVALID_SOCKET;}
              return 1;
    }         
    else
    {
              buf2[cyrobat_wserver_rc]='\0';
              cyrobat_wserver_rc=send(cyrobat_wserver_clients[cyrobat_wserver_client],buf,strlen(buf),0);
              strcpy(buf, buf2);
              return 0;
    }
}  


int wserverMULTISENDGET(char* buf, int cyrobat_wserver_client, bool cyrobat_wserver_wait)
{
    if(cyrobat_wserver_wait==1)
    {              
             while(cyrobat_wserver_clients[cyrobat_wserver_client]==INVALID_SOCKET)
             {
                           Sleep(100);
             }   
    }
    cyrobat_wserver_rc=send(cyrobat_wserver_clients[cyrobat_wserver_client],buf,strlen(buf),0);
    cyrobat_wserver_rc=recv(cyrobat_wserver_clients[cyrobat_wserver_client],buf,SIZE_STRING,0);
    if(cyrobat_wserver_rc==0 || cyrobat_wserver_rc==SOCKET_ERROR)
    {
                if(cyrobat_wserver_wait==true){log<<"#>Fehler: recv, fehler code: "<<WSAGetLastError()<<"\n";}
                if(WSAGetLastError()!=10038){cyrobat_wserver_clients[cyrobat_wserver_client]=INVALID_SOCKET;}
                return 1;
    }         
    else
    {
                buf[cyrobat_wserver_rc]='\0';
                return 0;
    }
}  


int wserverMULTISEND(char* buf, int cyrobat_wserver_client, bool cyrobat_wserver_wait)
{
    if(cyrobat_wserver_wait==1)
    {              
             while(cyrobat_wserver_clients[cyrobat_wserver_client]==INVALID_SOCKET)
             {
                           Sleep(100);
             }   
    }
    cyrobat_wserver_rc=send(cyrobat_wserver_clients[cyrobat_wserver_client],buf,strlen(buf),0);
    return 0;
} 


int wserverMULTIGET(char* buf, int cyrobat_wserver_client, bool cyrobat_wserver_wait)
{
    if(cyrobat_wserver_wait==true)
    {              
             while(cyrobat_wserver_clients[cyrobat_wserver_client]==INVALID_SOCKET)
             {
                           Sleep(100);
             }   
    }
    cyrobat_wserver_rc=recv(cyrobat_wserver_clients[cyrobat_wserver_client],buf,SIZE_STRING,0);
    if(cyrobat_wserver_rc==0 || cyrobat_wserver_rc==SOCKET_ERROR)
    {
                if(cyrobat_wserver_wait==true){log<<"#>Fehler: recv, fehler code: "<<WSAGetLastError()<<"\n";}
                if(WSAGetLastError()!=10038){cyrobat_wserver_clients[cyrobat_wserver_client]=INVALID_SOCKET;}
                return 1;
    }         
    else
    {
                buf[cyrobat_wserver_rc]='\0';
                return 0;
    }
}


int wserverMULTIEND()
{
  cyrobat_wserver_stat=0;  
  closesocket(cyrobat_wserver_acceptSocket);
  closesocket(cyrobat_wserver_connectedSocket);
  for(int i=0;i<MAX_CLIENTS;i++)
  {
                            closesocket(cyrobat_wserver_clients[i]);
  }
  WSACleanup();
  return 0;              
                 
}
#endif


cyrobat.h:
PHP:
//cyrobat.h
//Made by Cyrobat
#ifndef CYROBAT_H
#define CYROBAT_H


#ifndef WINSOCK_OFF
int wserverMULTISEND(char*,int,bool);
#endif


//***************************LOG***************************************
//log.h gibt einen die Möglichkeit alle ausgeben von cyrobat.h und 
//eigene Ausgaben in einer Logdatei mit Zeit und Datum zu speichern
//realisierbar über den Parameter log<<"text";
//Anwendung:
//#define LOG               //sagt das Log verwendet werden möchte 
//logSTART(path);           //muss am anfang stehen um LOG einzurichten
//logEND();                 //muss am Ende stehen um LOG zu schließen 
//______________________________________________________________________
#ifndef LOG                 //wenn LOG nicht definiert (änderbar)
#include <iostream>         //füge iostream ein
#define log std::cout       //ersetze log durch std::cout
#else                       //falls LOG definiert
#include "log.h"            //log.h einfügen
#endif 


//******************wclient - wserver************************************
//wclient.h gibt die Möglichkeit einen clienten zu erstellen
//wserver.h gibt die Möglichkeit einen Server zu erstellen einmal mit
//Multithearding und einmal ohne
//Anwendung:
//#define SIZESTRING 256    //Definiert die Maximallänge der Strings (änderbar)
//#define MAX_CLIENTS 10    //definiert die Anzahl der Maximalen Clienten von wserverMULTI (änderbar)
//            
//wclientSTART(IP,PORT);    //Zum starten und Connecten zun Server
//wclientSEND(char);        //Sendet string zum Server
//wclientGET(char);         //Empfängt string von Server
//wclientSENDGET(char);     //Sendet und Empfängt String auf einmal
//wclientGETSEND(char);     //Empfängt und Sendet einen String auf einmal
//wclientEND();             //Beendet die Verbindung zum Server
//
//wserverSTART(PORT);       //Startet Server auf jeweiligen Port
//wserverSEND(char);        //Sendet String zum Clienten
//wserverGET(char);         //Empfängt String vom Clienten
//wserverSENDGET(char);     //Sendet und Empfängt String auf einmal
//wserverGETSEND(char);     //Empfängt und Sendet String auf einmal
//wserverEND();             //Beendet Verbindung zum Clienten
//
//wserverMULTISTART(PORT);                     //Startet Multitheard Server auf jeweiligen Port
//wserverMULTISEND(char,client,warten);        //Sendet String zum Clienten(int)   bei warten(bool)=1 wird bis zu einer Eingabe gewartet
//wserverMULTIGET(char,client,warten);         //Empfängt String vom Clienten(int) bei warten(bool)=1 wird bis zu einer Eingabe gewartet
//wserverMULTISENDGET(char,client,warten);     //Sendet und Empfängt String auf einmal warten(bool)=1 wird bis zu einer Eingabe gewartet
//wserverMULTIGETSEND(char,client,warten);     //Empfängt und Sendet String auf einmal warten(bool)=1 wird bis zu einer Eingabe gewartet
//wserverMULTIEND();                           //Beendet Verbindungen zu den Clienten
//________________________________________________________________________
#ifndef WINSOCK_OFF          //wenn WINSOCK_OFF nicht definiert
#define SIZE_STRING 256      //definiert die Größe der Strings
#define MAX_CLIENTS 100       //definiert die Anzahl der Maximalen Clienten von wserverMULTI
#include "wclient.h"         //wclient.h einfügen
#include "wserver.h"         //wserver.h einfügen
#endif                       //if ende


//**************************cut********************************************
//Bietet die möglich keit einen string zu zerschneiden
//Anwendung:
//cut(char1, char2)          //char1 zu zerschneidenen string liefert 1 zerschnittenen string zurück
                             //char2 zeichen zum zerschneiden liefert 2 zerschnittenen string zurück               
#ifndef WWV_OFF              //wenn CUT_OFF nicht definiert
#include "wwv.h"             //cut.h einfügen
#endif                       //if ende                       


#endif

Falls Interesse besteht, hier mal die Header Dateien, sind aber noch nicht perfekt.
http://rapidshare.de/files/41188827/header.rar.html
 
Zuletzt bearbeitet:
Zurück