Server programmieren der mit mehreren Hundertausend Clienten klar kommt, Ideen?



  • surf schrieb:

    ich füge die neuen clients in einem vector ein, u wenn ein client eine message sendet wird mit FD_ISSET im vector nachgeschaut welcher client da was sendet...
    hab mal probiert 50 clients zu connecten...funzt prima ohne verzögerung (worst case 3 sekunden)

    also etwa so?

    for (i = 0; i < NumSocks; i++){
                if (FD_ISSET(ServSock[i], &SockSet))
                    break;
            }
    

    naja, wie lahm wird dieser code bei 100000 clients?
    richtig, sehr lahm wird er.

    ich arbeite ohne threads!

    fein. aber durch die schleife um FD_ISSET wirste bei vielen clients ja lahmer als die thread-version.

    was meint ihr zu der strategie?

    ich halte nix davon.
    win schenkt und io completion ports und thread pooling. was du mit ohne threads und FD_ISSET machen kannst, geht auch mit io completion ports, nur schneller. sind die reaktionen auf die pakete wirklich trivial und mit kaum rechenzeit verbunden, könnten threadwechsel relativ teuer sein.

    macht das icq auch so...ok der icq server gibt ja nur die online clients weiter? werden ja wohl kaum die messages über den icq server laufen? ich denk da wird zwischen den clients eine p2p connection erstellt? so wie auch beim filetransfer?

    ich weiß nicht, wie icq das gelöst hat. ich weiß nur, wie ich es lösen würde. ich würde die messages über den icq-server laufen lassen, damit die teilnehmer sich nicht gegenseitig die ip-adressen ausspähen können und dann angriffe fahren. aber ich würde mir was überlegen, daß ich von anfang an mit mehreren servern rechne.





  • also etwa so?

    for (i = 0; i < NumSocks; i++){
                if (FD_ISSET(ServSock[i], &SockSet))
                    break;
            }
    

    naja, wie lahm wird dieser code bei 100000 clients?
    richtig, sehr lahm wird er.

    win schenkt und io completion ports und thread pooling....

    wo find ich da infos über io completion ports drüber, möcht gerne wissen wie das funzt? mein chat client soll ja portabel sein, kann ich das auch für linux einsetzen?

    cu



  • IO Completion Ports funktionieren nur auf Windows. Und da nur auf den NT Versionen.

    Portabilität gleich 0.

    Und für deinen Chat wirst du das wohl kaum brauchen.



  • hallo!
    ich hab mal gehört sowas kann man unter linux mit
    Asynchronous I/O on linux, POSIX asynchronous I/O machen?

    cu



  • c.rackwitz schrieb:

    die 500-800k leute sind fakt. im moment sind es 777k, mit 1M als maximum, und das auf dem größten server. die anderen bringen auch nochmal locker ne million zusammen. quelle: http://www.razorback2.com

    das geht aber nur, weil die verbindungen nicht ständig offen gehalten werden. die clients machen nur anfragen und schliessen die verbindung dann wieder. ansonsten wären die 2^16 portnummern schnell aufgebraucht (so denke ich mir das. hat jemand genauere infos?). der eigentliche datenaustausch läuft eh' zwischen den teilnehmern und geht nicht über die server)



  • Hi!

    Ich hab mal vor 2 jahren einen kleinen Telnet-Server geproggt, der funktioniert aber leider nicht richtig (man kann sich aber dort anmelden, usw.) der unterstüzt mehrere Clients.

    Kannst ja vielleicht was davon gebrauchen:

    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    #include <conio.h>
    #define MAXCLIENTS 10
    
    struct clients
    {
            char name[256];
            int socket;
    };
    
    int main()
    {
            long rc;
            int clients = 0;
            int selectres;
            SOCKET acceptSocket;
            SOCKET connectedSocket[MAXCLIENTS];
            SOCKADDR_IN addr;
            char buf[256];
            char buf2[300];
            WSADATA wsa;
            fd_set fds;
    
            //Timer für select
            struct timeval tv;
            tv.tv_sec=5;
            tv.tv_usec=50000;
    
            printf("Loading winsock...");
            rc = WSAStartup(MAKEWORD(2,0),&wsa);
    
            if(rc!=0)
            {
                    printf("Failed: %d\n",rc);
                    return 1;
            }
            else
            {
                    printf("Done\n");
            }
    
            printf("Loading socket...");
    
            acceptSocket=socket(AF_INET,SOCK_STREAM,0); //IPPROTO_TCP ??
    
            if(acceptSocket==INVALID_SOCKET)
            {
                    printf("Failed\n");
                    return 1;
            }
            else
            {
                    printf("Done\n");
            }
    
            printf("Starting server...");
            memset(&addr,0,sizeof(SOCKADDR_IN));
            addr.sin_family=AF_INET;
            addr.sin_port=htons(21); //Port
            addr.sin_addr.s_addr=ADDR_ANY;
            rc = bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));
            if(rc==SOCKET_ERROR)
            {
                    printf("Failed\n");
                    return 1;
            }
            else
            {
                    printf("Done\n");
            }
    
            listen(acceptSocket,MAXCLIENTS);
            connectedSocket[0] = accept(acceptSocket,NULL,NULL);
            send(connectedSocket[0],"Hello World :))\n",256,0);
            clients++;
    
            while(selectres != -1)
            {
                    FD_ZERO(&fds);
    
                            //if(i > clients) break;
    
                                            /*
                    for(int i = 0;i < clients;i++)
                    {
                            //fcntl(connectedSocket[i], F_SETFL, O_NONBLOCK);
                            FD_SET(connectedSocket[i],&fds);
                    }                         */
                    FD_SET(connectedSocket[0],&fds);
                    printf("Listening...\n");
                    /*
                    for(int  i = 0;i<fds.fd_count; i++)
                    {
                            printf("%d %d\n", fds.fd_array[i], i);
                    }
                    getch();
                    */
                    selectres = select(MAXCLIENTS+1,&fds,&fds,NULL,&tv);
    
                    printf("Select result: %d\n", selectres);
    
                    for(int i=0;i < MAXCLIENTS;i++)
                    {
                            printf("Test: %d %d %d\n", selectres, i ,FD_ISSET(i,&fds));
                            if(FD_ISSET(connectedSocket[i],&fds))
                            {
                                    switch(selectres)
                                    {
                                            case 0: break;
                                            case 1:
                                                    //connectedSocket[0] = accept(acceptSocket,NULL,NULL);
                                                    printf("waiting for receive\n");
                                                    rc = recv(connectedSocket[i],buf,256,0);
                                                    if(rc > 0)
                                                    {
                                                            buf[rc]='\0';
                                                            printf("Client: %s\n",buf);
                                                            sprintf(buf2,"Answering you request: %s", buf);
                                                            printf("Sending...\n",buf);
                                                            rc = send(connectedSocket[i],buf2,strlen(buf2),0);
                                                    }
                                                    break;
                                    }
                            }
                    }
                    //listen(acceptSocket,0)
            }
    
            for(int i = 0;i<MAXCLIENTS;i++)
            {
                    closesocket(connectedSocket[i]);
            }
            WSACleanup();
            getch();
            return 0;
    }
    

    Wie gesagt funktioniert nicht richtig, aber mit telnet kann man sich dort anmelden.

    Gruss,
    ~code_pilot



  • net schrieb:

    c.rackwitz schrieb:

    die 500-800k leute sind fakt. im moment sind es 777k, mit 1M als maximum, und das auf dem größten server. die anderen bringen auch nochmal locker ne million zusammen. quelle: http://www.razorback2.com

    das geht aber nur, weil die verbindungen nicht ständig offen gehalten werden. die clients machen nur anfragen und schliessen die verbindung dann wieder. ansonsten wären die 2^16 portnummern schnell aufgebraucht (so denke ich mir das. hat jemand genauere infos?). der eigentliche datenaustausch läuft eh' zwischen den teilnehmern und geht nicht über die server)

    was meinst du dazu volkard??? einer sagt das läuft über den icq server, der andere sagt nein...hmmm

    cu



  • surf schrieb:

    net schrieb:

    ....ansonsten wären die 2^16 portnummern schnell aufgebraucht...

    was meinst du dazu volkard??? einer sagt das läuft über den icq server, der andere sagt nein...hmmm

    das war natürlich quatsch, weil ip-adresse und portnummer zusammen einen socket eindeutig identifizieren d.h. 2^32 * 2^16 = 2^48 verbindungen könnte ein server theoretisch gleichzeitig mit tcp/ip offen halten (vorausgesetzt er hat soviel speicher ;)).



  • ein razorback2 edonkey server hat 12 gigabyte ram... da passt was rein 😉



  • surf schrieb:

    was meinst du dazu volkard??? einer sagt das läuft über den icq server, der andere sagt nein...hmmm

    deine eine meint auch, eine verbindung bestünde auch 2 sockets, wobei ein socket aus ip-adresse und port bestünde.
    und der andere meint, bei 2^16 sei ende gelände, weil nichtmal die gegnerische ip-adresse bedeutsam genug sei, um zwei verbindungen als unterschiedlich zu erkennen.
    außerdem kann sehr wohl alles über den server laufen, ohne daß die verbindungen offen sind. es gibt ja auch udp und nicht nur tcp. und tcp-connections könnten auch nen schnellen timeout haben. sehe keine gründe, es nicht über den server laufen zu lassen. sehe gewichtige gründe, es über den server laufen zu lassen. hab aber keine sicheren infos, wie sie es tatsächlich machen.



  • surf schrieb:

    wo find ich da infos über io completion ports drüber, möcht gerne wissen wie das funzt? mein chat client soll ja portabel sein, kann ich das auch für linux einsetzen?

    der client bleibt protabel. den machste mit select oder wie du mags. voll portabel. der hat nullinger speedprobleme.

    der server benutzt unter win iocompletion ports und evtl thread pooling. ser server wird auf jeden fall unportabel, um high speed rauszuholen.


Anmelden zum Antworten