Parallele Verbindungen



  • Ich hab jetzt mal selber einen Server geschrieben. Allerdings funktioniert der noch nicht so richtig:

    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    #define BUF_SIZE 255
    
    int Port = 12345;
    
    long rc;
    SOCKET acceptSocket;
    SOCKET connectedSocket;
    SOCKADDR_IN addr;
    
    int Clientenanzahl;
    
    int Verbindung;
    
    char Zahl1[900];
    char Zahl2[900];
    
    FD_SET fdSet;
    SOCKET clients[100];
    int i;
    
    int antwortlaenge1;
    int antwortlaenge2;
    int Laenge1;
    int Laenge2; 
    char buffer1[100];
    char buffer2[100];
    char juhu[900];
    
    typedef struct MyData {
        int data;
    } MYDATA, *PMYDATA;
    
    PMYDATA pDataArray[100];
    
    int startWinsock(void)
    {
      WSADATA wsa;
      return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    
    DWORD WINAPI NeuerClient(LPVOID lpParam) 
    { 
        HANDLE hStdout;
        PMYDATA pDataArray;
        int nummer;
    
        TCHAR msgBuf[BUF_SIZE];
        size_t cchStringSize;
        DWORD dwChars;
    
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
        if( hStdout == INVALID_HANDLE_VALUE )
            return 1;
    
        pDataArray = (PMYDATA)lpParam;
    
        nummer=pDataArray->data;
    
        printf("%d.Client\n",nummer);
        while(1) 
        { 
                 antwortlaenge1 = recv(clients[nummer], buffer1, 1, 0);
                 buffer1[antwortlaenge1] = '\0';
                 Laenge1 = atoi(buffer1);
    
                 antwortlaenge2 = recv(clients[nummer], buffer2, Laenge1, 0);
                 buffer2[antwortlaenge2] = '\0';
                 Laenge2 = atoi(buffer2);
    
                 Verbindung=recv(clients[nummer],juhu,Laenge2,0); 
                 if(Verbindung==SOCKET_ERROR) 
                 { 
                                  break;
                 }
                 juhu[Verbindung]='\0';
        }
    return 0; 
    }
    
    int main(int argc, char *argv[])
    {
    
      rc=startWinsock();
      if(rc!=0)
      {
             printf("\r\nWinsock konnte nicht gestartet werden!\r\n");
             return 0;
      }
      else
      {
              printf("\r\nWinsock gestartet!\r\n");
      }
    
      acceptSocket=socket(AF_INET,SOCK_STREAM,0);
      if(acceptSocket==INVALID_SOCKET)
      {
                    printf("Fehler: Der Socket konnte nicht erstellt werden!\r\n");
                    return 0;
      }
      else
      {
                    printf("Socket erstellt!\r\n");
      }
    
      memset(&addr,0,sizeof(SOCKADDR_IN));
      addr.sin_family=AF_INET;
      addr.sin_port=htons(Port);
      addr.sin_addr.s_addr=ADDR_ANY;
    
      rc=bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));
      if(rc==SOCKET_ERROR)
      {
                 printf("Socket konnte nicht an den Port 12345 gebunden werden!\r\n");
                 return 0;
      }
      else
      {
                 printf("Socket an Port 12345 gebunden\r\n");
      }
    
      rc=listen(acceptSocket,100);
      if(rc==SOCKET_ERROR)
      {
                          printf("acceptSocket ist nicht im listen Modus!\r\n");
                          return 0;
      }
      else
      {
                          printf("acceptSocket ist im listen Modus...\r\n"); 
      }
      while(1) 
      { 
                sleep(10);
                FD_ZERO(&fdSet); // Inhalt leeren
                FD_SET(acceptSocket,&fdSet); // Den Socket der verbindungen annimmt hinzufügen
    
        // alle gültigen client sockets hinzufügen (nur die die nicht INVALID_SOCKET sind)
                for(i=0;i<100;i++) 
                {
                            if(clients[i]!=INVALID_SOCKET)
                            {
                                           FD_SET(clients[i],&fdSet);
                            }
                }
    
                rc=select(0,&fdSet,NULL,NULL,NULL); // nicht vergessen den ersten parameter bei anderen betriebssystem anzugeben
                if(rc==SOCKET_ERROR) 
                {
                  //return 0;
                }
    
                // acceptSocket is im fd_set? => verbindung annehmen (sofern es platz hat)
                if(FD_ISSET(acceptSocket,&fdSet)) 
                {
                          // einen freien platz für den neuen client suchen, und die verbingung annehmen
                          for(i=0;i<100;i++)
                          {
                                       if(clients[i]==INVALID_SOCKET) 
                                       {
                                                  clients[i]=accept(acceptSocket,NULL,NULL);//akzeptieren
                                                  printf("Neuer Client\n");
    
                                                  pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,sizeof(MYDATA));
                                                  pDataArray[i]->data = i;
    
                                                  CreateThread(NULL, 0, NeuerClient, pDataArray[i], 0, NULL);
                                                  break;
                                       }
                          }
                }
    
                // prüfen welcher client sockets im fd_set sind
                for(i=0;i<100;i++) 
                {
                            if(clients[i]==INVALID_SOCKET)
                            {
                                              continue; // ungültiger socket, d.h. kein verbunder client an dieser position im array
                            }
                            if(FD_ISSET(clients[i],&fdSet))
                            {
                                          //Client will was schicken                                                                                 
                            }
                }
    
      } 
    
      return 0;
    }
    

    Was ist da falsch?



  • Nein, Threads sind nicht notwendig. Ich wäre mit Threads überhaupt sparsam. Das Zauberwort heißt "Asynchron". Du musst die FD_XXX Funktionen ersetzen durch WSA_XXX, also WSAWaitForMultipleEvents usw. Dann kannst Du in einem Thread (dem Hauptthread der Anwendung) beliebig viele Sockets bedienen. Dieses ganze FD_XXX Zeug funktioniert unter Windows nicht richtig!



  • Dieses ganze FD_XXX Zeug funktioniert unter Windows nicht richtig!

    rofl. klar funktioniert das.



  • hajoe schrieb:

    Dieses ganze FD_XXX Zeug funktioniert unter Windows nicht richtig!

    olo 👍



  • Schon mal was von "Editieren" gehört? Das gibts in jedem noch so verschissenen Forum, und bestimmt nicht, damit es nicht benutzt wird ... nur so btw.



  • @ hajoe: Das Problem ist jetzt nur, dass ich mit Dev-C++ arbeite und da funktioniert getaddrinfo und freeaddrinfo irgendwie nicht. Ich hab alle möglichen .a eingebunden und die richtigen Bibliotheken, aber es geht nicht. Geht das auch ohne die Funktionen oder muss ich doch auf VC++ umsteigen?



  • Ich verstehe das Problem nicht, Du musst doch nur die Funktionen der WinSocket-API einbinden. Übrigens, wenn hier jemand meint die FD_XXX Funktionen tun genau das, was sie sollen, kann er sie ja verwenden, ich tu's nicht (aus Erfahrung).



  • Wenn ich das Beispielprogramm auf MSDN zu WSARecv kompilieren will. Kommen folgende Fehler nachdem ich libws2_32.a und libwsock32.a eingebunden habe:

    wsa neu recv.o(.text+0x145):wsa neu recv.c: undefined reference to `getaddrinfo'
    wsa neu recv.o(.text+0x200):wsa neu recv.c: undefined reference to `freeaddrinfo'
    wsa neu recv.o(.text+0x2a7):wsa neu recv.c: undefined reference to `freeaddrinfo'
    wsa neu recv.o(.text+0x300):wsa neu recv.c: undefined reference to `freeaddrinfo'
    wsa neu recv.o(.text+0x354):wsa neu recv.c: undefined reference to `freeaddrinfo'
    wsa neu recv.o(.text+0x556):wsa neu recv.c: undefined reference to `freeaddrinfo'
    

    Den Quellcode könnt ihr bei MSDN hier finden: http://msdn2.microsoft.com/en-us/library/ms741688(VS.85).aspx



  • Verwende doch einfach dynamisches Linking, also z.B. so:

    typedef void (WINAPI *FunctionProc) (Parameterliste);

    FunctionProc IrgendeineFunktion;

    HANDLE h = LoadLibrary ("Ws2_32.dll");

    IrgendeineFunktion = (FunctionProc) GetProcAddress (h,"NameDerFunktion");



  • lol oder verwendte ne anständige Entwicklungsumgebung und nicht so einen SCHROTT



  • Welche Entwicklungsumgebung kannst du mir außer VC++ empfehlen?





  • Vielen Dank @ hajoe. Du hast mir wirklich geholfen. Alles klappt wunderbar.



  • Wenn du die Funktion mit GetProcAddress lädst funktioniert dein Programm erst ab Windows XP. Bei Visual C++ ist es so das es einen Header namens Wspiapi.h gibt in der die Funktion emuliert wird so das es auch auf älteren Betriebssystemen läuft. Bei der MinGW Suite, die von Dev-C++ genutzt wird, gibt es diese Header-Datei nicht.

    Da du anscheinend Visual C++ nicht magst würde ich dir CodeBlocks mit Visual C++ Compiler empfehlen. Visual C++ muss dann zwar trotzdem installiert sein, aber du kriegst es nicht zu Gesicht. 😉



  • Danke, ich versuchs dann mal mit CodeBlocks.



  • ä schrieb:

    Da du anscheinend Visual C++ nicht magst würde ich dir CodeBlocks mit Visual C++ Compiler empfehlen. Visual C++ muss dann zwar trotzdem installiert sein, aber du kriegst es nicht zu Gesicht. 😉

    lol wie sinnlos. hauptsache ich tausch die beste IDE, die es gibt, gegen eine völlig verbuggte IDE, die in keiner hinsicht mit VS mithalten kann...... 👎



  • Felix15 schrieb:

    Danke, ich versuchs dann mal mit CodeBlocks.

    lol viel spaß, du tauschst einen haufen schrott gegen den nächsten 🤡



  • bitte nicht auf real_rofler hören



  • ich bin hier im winapi forum der junior boss, also sehr wohl auf mich hören. fragen wir doch jochen kalmbach was besser ist. VC2008 oder CodeBlocks.



  • @Felix15: Ich habe gerade mal gegooglt und gesehen das man die wspiapi.h aus dem Platform SDK nehmen kann, man muss nur _inline durch __inline ersetzen. So könntest du also noch bei Dev-C++ bleiben, auch wenn es nicht empfehlenswert ist.


Anmelden zum Antworten