WebHU - Programozási kérdések és válaszok

A C++ hálózatban a select használatával először meg kell figyelnem () és elfogadnom ()?

Megpróbálom lehetővé tenni, hogy több kliens csatlakozzon egy gazdagéphez a select használatával. Mindegyiket csatlakoztatnom kell, mondanom kell nekik, hogy menjenek át egy másik portra, majd csatlakozzanak újra egy új porton? Vagy az engedélyezi, hogy több klienst csatlakoztassak ugyanahhoz a porthoz?

Ez a kliens kód:

    int rv;
int sockfd, numbytes;

if ((rv = getaddrinfo(hostName, hostPort, &hints, &servinfo)) != 0) {
    cout << "Could not get server address.\n";
    exit(1);
}

// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
        perror("Client: no socket");
        continue;
    }

    if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
        close(sockfd);
        perror("Client: connect");
        continue;
    }

    break;
}

if (p == NULL) {
    fprintf(stderr, "Unable to connect to server.\n");
    exit(2);
}

FD_SET(sockfd, &masterSet);

Ez a szerver kódja:

        int rv = getaddrinfo(NULL, port, &hints, &res);
    int yes = 1;//Not sure what this is for, found it in Beej's
    if(rv != 0){
            cout<< "Error, nothing matches criteria for file descriptor.\n";
            exit(1);
    }
    int fdInit;
    for(temp = res; temp != NULL; temp = temp->ai_next){
            if((fdInit = socket(temp->ai_family, temp->ai_socktype, temp->ai_protocol)) == -1){
                    cout << "This is not the fd you're looking for.  Move along.\n";
                    continue; //This is not the fd you're looking for, move along.
            }

            if(setsockopt(fdInit, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
                    cout << "Doom has fallen upon this set socket.\n";
                    perror("setsockopt");
                    exit(1); //Unable to set socket, exit program with code 1
            }

            if(bind(fdInit, temp->ai_addr, temp->ai_addrlen) == -1){
                    cout << "Could not bind fd\n";
                    close(fdInit);
                    continue; //Could not bind fd, continue looking for valid fd
            }
            break; //If a valid fd has been found, stop checking the list
    }
    if(temp==NULL){
            cout<<"Server failed to bind a socket\n";
            exit(2);
    }

    cout << fdInit << endl;
    //Setup the file descriptor for initial connections on specified port
    freeaddrinfo(res);
    FD_SET(fdInit, &masterSet);

Bármilyen segítség kiváló lenne! Kösz.


Válaszok:


1

A TCP-kapcsolatokat a kapcsolat két végének IP-címe és portszáma azonosítja. Ezért jó, ha sok kliens (amelyek általában véletlenszerűen hozzárendelt portszámokkal rendelkeznek) egyetlen szerverporthoz csatlakoznak.

Létrehozol egy socketet, bind() egy portra, amelyen listen(), majd megvárod, amíg az ügyfelek kopogtatnak rajta. Ha nem bánja, ha blokkolja, akkor csak közvetlenül hívhatja a accept() számot, de nem fog tudni időtúllépési ciklust vagy ilyesmit csinálni. Ellenkező esetben select() a lehallgató aljzaton, amely olvashatóvá válik, amikor egy kliens megpróbál csatlakozni, majd hívja a accept() számot.

A accept() egy újonnan létrehozott socketet ad vissza, amely az a socket, amelyen az ügyféllel beszélni kell. Az eredeti lehallgató aljzat tovább hallgat, és több csatlakozás is fogadható rajta.

Jellemző, hogy egy select() hurkot használnak az olvashatóság keresésére a hallgatási aljzaton és a csatlakoztatott aljzatok bármelyikén. Aztán amikor a select() visszatér, egyszerűen ellenőrizze, hogy a lehallgató aljzat olvasható volt-e, és ha igen, akkor accept(); egyébként keress egy olvasható csatlakoztatott aljzatot és kezeld.

fd_set fds;
int max = 0, reuse = 1;
struct timeval tv;
int server;
std::vector<int> connected;

// create server listening socket
server = socket(PF_INET, SOCK_STREAM, getprotobyname("tcp")->p_proto);
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)); // optional, but recommended
if (bind(server, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
    // error, could not bind server socket
}
if (listen(server, 8) < 0) {
    // error, could not listen on server port
}

// loop looking for connections / data to handle
while (running) {
    FD_ZERO(&fds);
    FD_SET(server, &fds);
    if (server >= max) max = server + 1;

    for (std::vector<int>::iterator it = connected.begin(); it != connected.end(); ++it) {
        FD_SET(*it, &fds);
        if (*it >= max) max = *it + 1;
    }

    tv.tv_sec = 2; tv.tv_usec = 0;
    if (select(max, &fds, NULL, NULL, &tv) > 0) {
        // something is readable
        if (FD_ISSET(server, &fds)) {
            // it's the listener
            connected.push_back(accept(server, (struct sockaddr *)&addr));
        }
        for (std::vector<int>::iterator it = connected.begin(); it != connected.end(); ++it) {
            if (FD_ISSET(*it, &fds)) {
                // handle data on this connection
            }
        }
    }
}
17.02.2010

2

sok kliens csatlakozhat ugyanahhoz a porthoz

először meg kell hallgatnia, majd kiválasztania

amikor a kiválasztás azt jelzi, hogy új kapcsolat van, akkor fogadja el. Azt mondja, hogy a kliens csatlakozott az fd socket olvasási jelzésével.

17.02.2010

3

Meg kell jelölnie a szerver socketet (listen(2)), de csak akkor hívja meg a accept(2)-t, amikor visszatér a select(2)-ból, amikor az olvashatóvá válik - ez azt jelenti, hogy új csatlakozási kérelem függőben van.

Kérjük, vegye figyelembe, hogy ha nem nem blokkoló socketekkel dolgozik, lehetséges, hogy versenyez select(2) visszatérés és accept(2) - a csatlakozó kliens - hívása között. ezalatt megszakíthatja a kísérletet – így továbbra is blokkolhat.

17.02.2010
Új anyagok

A rádiógomb ellenőrzött eseményének használata a jQueryben
Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

Miért érdemes elkezdeni a kódolást 2023-ban?
01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

🎙 Random Noise #2  – Örökbefogadás és hit
az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..